Skip to content

Commit

Permalink
refactor: remove Format constructor (#17)
Browse files Browse the repository at this point in the history
We remove the Format constructor in Pp.t that prevented it from being
drectly serializable.

Signed-off-by: Ali Caglayan <[email protected]>
  • Loading branch information
Alizter authored Oct 18, 2023
1 parent 86281b1 commit faf15db
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 95 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
Unreleased
----------

- Remove `of_fmt` constructor. (#17, @Alizter)

1.2.0
-----

Expand Down
65 changes: 3 additions & 62 deletions src/pp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,59 +24,10 @@ module Ast = struct
| Tag of 'a * 'a t
end

type +'a t =
| Nop
| Seq of 'a t * 'a t
| Concat of 'a t * 'a t list
| Box of int * 'a t
| Vbox of int * 'a t
| Hbox of 'a t
| Hvbox of int * 'a t
| Hovbox of int * 'a t
| Verbatim of string
| Char of char
| Break of (string * int * string) * (string * int * string)
| Newline
| Text of string
| Tag of 'a * 'a t
| Format of (Format.formatter -> unit)
include Ast

let rec of_ast : 'a. 'a Ast.t -> 'a t = function
| Nop -> Nop
| Seq (x, y) -> Seq (of_ast x, of_ast y)
| Concat (x, y) -> Concat (of_ast x, List.map ~f:of_ast y)
| Box (x, y) -> Box (x, of_ast y)
| Vbox (x, y) -> Vbox (x, of_ast y)
| Hbox x -> Hbox (of_ast x)
| Hvbox (x, y) -> Hvbox (x, of_ast y)
| Hovbox (x, y) -> Hovbox (x, of_ast y)
| Verbatim s -> Verbatim s
| Char c -> Char c
| Break (x, y) -> Break (x, y)
| Newline -> Newline
| Text s -> Text s
| Tag (a, x) -> Tag (a, of_ast x)

let to_ast x =
let rec to_ast : 'a t -> 'a Ast.t = function
| Nop -> Nop
| Seq (x, y) -> Seq (to_ast x, to_ast y)
| Concat (x, y) -> Concat (to_ast x, List.map ~f:(fun x -> to_ast x) y)
| Box (x, y) -> Box (x, to_ast y)
| Vbox (x, y) -> Vbox (x, to_ast y)
| Hbox x -> Hbox (to_ast x)
| Hvbox (x, y) -> Hvbox (x, to_ast y)
| Hovbox (x, y) -> Hovbox (x, to_ast y)
| Verbatim s -> Verbatim s
| Char c -> Char c
| Break (x, y) -> Break (x, y)
| Newline -> Newline
| Tag (a, x) -> Tag (a, to_ast x)
| Text s -> Text s
| Format _ -> raise_notrace Exit
in
try Ok (to_ast x) with
| Exit -> Error ()
let of_ast = Fun.id
let to_ast = Fun.id

let rec map_tags t ~f =
match t with
Expand All @@ -90,7 +41,6 @@ let rec map_tags t ~f =
| Hovbox (indent, t) -> Hovbox (indent, map_tags t ~f)
| (Verbatim _ | Char _ | Break _ | Newline | Text _) as t -> t
| Tag (tag, t) -> Tag (f tag, map_tags t ~f)
| Format f -> Format f

let rec filter_map_tags t ~f =
match t with
Expand All @@ -109,7 +59,6 @@ let rec filter_map_tags t ~f =
match f tag with
| None -> t
| Some tag -> Tag (tag, t))
| Format f -> Format f

module Render = struct
open Format
Expand Down Expand Up @@ -152,7 +101,6 @@ module Render = struct
| Newline -> pp_force_newline ppf ()
| Text s -> pp_print_text ppf s
| Tag (tag, t) -> tag_handler ppf tag t
| Format f -> f ppf
end

let to_fmt_with_tags = Render.render
Expand Down Expand Up @@ -223,8 +171,6 @@ module O = struct
let ( ++ ) = seq
end

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

let compare =
let compare_both (type a b) (f : a -> a -> int) (g : b -> b -> int) (a, b)
(c, d) =
Expand Down Expand Up @@ -299,10 +245,5 @@ let compare =
| 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
35 changes: 15 additions & 20 deletions src/pp.mli
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
(** Pretty-printing. *)

(** A document that is not yet rendered. The argument is the type of tags in the
document. For instance tags might be used for styles. *)
(** ['tag t] represents a document that is not yet rendered. The argument ['tag]
is the type of tags in the document. For instance tags might be used for
styles.
If you want to serialise and deserialise this datastructure, you can use the
[Ast.t] type together with the [of_ast] and [to_ast] functions. *)
type +'tag t

(** {1 Basic combinators} *)
Expand Down Expand Up @@ -191,20 +195,14 @@ val to_fmt_with_tags :
-> tag_handler:(Format.formatter -> 'tag -> 'tag t -> unit)
-> unit

(** {1 Injection} *)

(** Inject a classic formatter in a document.
Disclaimer: this function is to meant to help using [Pp] in existing code
that already use the [Format] module without having to port everything to
[Pp]. It is not meant as the normal way to create [Pp.t] values. *)
val of_fmt : (Format.formatter -> 'tag -> unit) -> 'tag -> 'tag t

(** {1 Ast} *)

module Ast : sig
(** Stable representation useful for serialization *)
type 'tag t =
(** Stable representation of [Pp.t] useful for serialization *)

(** Stable abstract syntax tree for [Pp.t] that can be used for serialization
and deserialization. *)
type +'tag t =
| Nop
| Seq of 'tag t * 'tag t
| Concat of 'tag t * 'tag t list
Expand All @@ -221,16 +219,13 @@ module Ast : sig
| Tag of 'tag * 'tag t
end

(** [of_ast t] [Ast.t] to [Pp.t] *)
(** [of_ast t] converts an [Ast.t] to a [Pp.t]. *)
val of_ast : 'tag Ast.t -> 'tag 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 : 'tag t -> ('tag Ast.t, unit) result
(** [to_ast t] converts a [Pp.t] to an [Ast.t]. *)
val to_ast : 'tag t -> 'tag Ast.t

(** {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. *)
(** [compare cmp x y] compares [x] and [y] using [cmp] to compare tags. *)
val compare : ('tag -> 'tag -> int) -> 'tag t -> 'tag t -> int
13 changes: 0 additions & 13 deletions test/tests.ml
Original file line number Diff line number Diff line change
Expand Up @@ -209,19 +209,6 @@ 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 pp_pair ppf (a, b) = Format.fprintf ppf "(%i,@ %i)" a b

let%expect_test _ =
print
(Pp.text "hello" ++ Pp.newline
++ Pp.vbox (Pp.of_fmt pp_pair (1, 2))
++ Pp.space ++ Pp.text "foo");
[%expect {|
hello
(1,
2)
foo |}]

let%expect_test "comparison" =
let x = error_example_1
and y = Pp.hovbox ~indent:2 (xs 200) in
Expand Down

0 comments on commit faf15db

Please sign in to comment.