Skip to content

Commit 0342632

Browse files
committed
Add json mapper for pp_ast
Signed-off-by: Pedro B S Lisboa <[email protected]>
1 parent 7a6ce40 commit 0342632

File tree

6 files changed

+655
-99
lines changed

6 files changed

+655
-99
lines changed

Diff for: CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
unreleased
22
----------
33

4+
- Add custom printer support to `pp_ast` functions via the `?printer` config parameter.
5+
46
0.34.0 (2025-01-06)
57
-------------------
68

Diff for: bin/dune

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
(name pp_ast)
33
(public_name ppxlib-pp-ast)
44
(package ppxlib-tools)
5-
(libraries cmdliner ppxlib ppxlib.ast ppxlib.astlib ppxlib.stdppx))
5+
(libraries cmdliner ppxlib ppxlib.ast ppxlib.astlib ppxlib.stdppx yojson))

Diff for: bin/pp_ast.ml

+35-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,29 @@ module Ast = struct
1818
| Typ of core_type
1919
end
2020

21+
let rec repr_to_yojson : Pp_ast.repr -> Yojson.Basic.t = function
22+
| Unit -> `Null
23+
| Int i -> `Int i
24+
| String s -> `String s
25+
| Special s -> `String s
26+
| Bool b -> `Bool b
27+
| Char c -> `String (String.make 1 c)
28+
| Float f -> `Float f
29+
| Int32 i32 -> `Int (Int32.to_int i32)
30+
| Int64 i64 -> `Int (Int64.to_int i64)
31+
| Nativeint ni -> `Int (Nativeint.to_int ni)
32+
| Array l -> `List (List.map repr_to_yojson l)
33+
| Tuple l -> `List (List.map repr_to_yojson l)
34+
| List l -> `List (List.map repr_to_yojson l)
35+
| Record fields ->
36+
`Assoc (List.map (fun (k, v) -> (k, repr_to_yojson v)) fields)
37+
| Constr (cname, []) -> `String cname
38+
| Constr (cname, [ x ]) -> `Assoc [ (cname, repr_to_yojson x) ]
39+
| Constr (cname, l) -> `Assoc [ (cname, `List (List.map repr_to_yojson l)) ]
40+
41+
let json_printer fmt value =
42+
Yojson.Basic.pretty_print fmt (repr_to_yojson value)
43+
2144
module Input = struct
2245
type t = Stdin | File of string | Source of string
2346

@@ -97,6 +120,10 @@ let loc_mode =
97120
in
98121
named (fun x -> `Loc_mode x) Cmdliner.Arg.(value & vflag `Short [ full_locs ])
99122

123+
let json =
124+
let doc = "Show AST as json" in
125+
named (fun x -> `Json x) Cmdliner.Arg.(value & flag & info ~doc [ "json" ])
126+
100127
let kind =
101128
let make_vflag (flag, (kind : Kind.t), doc) =
102129
(Some kind, Cmdliner.Arg.info ~doc [ flag ])
@@ -126,7 +153,7 @@ let input =
126153
let errorf fmt = Printf.ksprintf (fun s -> Error s) fmt
127154

128155
let run (`Show_attrs show_attrs) (`Show_locs show_locs) (`Loc_mode loc_mode)
129-
(`Kind kind) (`Input input) =
156+
(`Json json) (`Kind kind) (`Input input) =
130157
let open Stdppx.Result in
131158
let kind =
132159
match kind with
@@ -147,13 +174,18 @@ let run (`Show_attrs show_attrs) (`Show_locs show_locs) (`Loc_mode loc_mode)
147174
match input with Stdin -> "<stdin>" | File fn -> fn | Source _ -> "<cli>"
148175
in
149176
let ast = load_input ~kind ~input_name input in
150-
let config = Pp_ast.Config.make ~show_attrs ~show_locs ~loc_mode () in
177+
let custom_printer = if json then Some json_printer else None in
178+
let config =
179+
Pp_ast.Config.make ~show_attrs ~show_locs ~loc_mode ?printer:custom_printer
180+
()
181+
in
151182
pp_ast ~config ast;
152183
Format.printf "%!\n";
153184
Ok ()
154185

155186
let term =
156-
Cmdliner.Term.(const run $ show_attrs $ show_locs $ loc_mode $ kind $ input)
187+
Cmdliner.Term.(
188+
const run $ show_attrs $ show_locs $ loc_mode $ json $ kind $ input)
157189

158190
let tool_name = "ppxlib-pp-ast"
159191

Diff for: src/pp_ast.ml

+92-83
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,20 @@
11
open Import
22

3-
module Config = struct
4-
type loc_mode = [ `Short | `Full ]
5-
type t = { show_attrs : bool; show_locs : bool; loc_mode : loc_mode }
6-
7-
module Default = struct
8-
let show_attrs = false
9-
let show_locs = false
10-
let loc_mode = `Short
11-
end
12-
13-
let default =
14-
let open Default in
15-
{ show_attrs; show_locs; loc_mode }
16-
17-
let make ?(show_attrs = Default.show_attrs) ?(show_locs = Default.show_locs)
18-
?(loc_mode = Default.loc_mode) () =
19-
{ show_attrs; show_locs; loc_mode }
20-
end
21-
22-
let cnum (pos : Lexing.position) = pos.pos_cnum - pos.pos_bol
23-
24-
type simple_val =
3+
type repr =
254
| Unit
265
| Int of int
276
| String of string
287
| Bool of bool
298
| Char of char
30-
| Array of simple_val list
9+
| Array of repr list
3110
| Float of float
3211
| Int32 of int32
3312
| Int64 of int64
3413
| Nativeint of nativeint
35-
| Record of (string * simple_val) list
36-
| Constr of string * simple_val list
37-
| Tuple of simple_val list
38-
| List of simple_val list
14+
| Record of (string * repr) list
15+
| Constr of string * repr list
16+
| Tuple of repr list
17+
| List of repr list
3918
| Special of string
4019

4120
let pp_collection ~pp_elm ~open_ ~close ~sep fmt l =
@@ -46,8 +25,11 @@ let pp_collection ~pp_elm ~open_ ~close ~sep fmt l =
4625
List.iter tl ~f:(fun sv -> Format.fprintf fmt "%s %a@," sep pp_elm sv);
4726
Format.fprintf fmt "%s@]" close
4827

49-
let rec pp_simple_val fmt simple_val =
50-
match simple_val with
28+
type 'a pp = Format.formatter -> 'a -> unit
29+
30+
let rec pp_repr : repr pp =
31+
fun fmt repr ->
32+
match repr with
5133
| Unit -> Format.fprintf fmt "()"
5234
| Int i -> Format.fprintf fmt "%i" i
5335
| String s -> Format.fprintf fmt "%S" s
@@ -59,27 +41,55 @@ let rec pp_simple_val fmt simple_val =
5941
| Int64 i64 -> Format.fprintf fmt "%Li" i64
6042
| Nativeint ni -> Format.fprintf fmt "%ni" ni
6143
| Array l ->
62-
pp_collection ~pp_elm:pp_simple_val ~open_:"[|" ~close:"|]" ~sep:";" fmt l
44+
pp_collection ~pp_elm:pp_repr ~open_:"[|" ~close:"|]" ~sep:";" fmt l
6345
| Tuple l ->
64-
pp_collection ~pp_elm:pp_simple_val ~open_:"(" ~close:")" ~sep:"," fmt l
65-
| List l ->
66-
pp_collection ~pp_elm:pp_simple_val ~open_:"[" ~close:"]" ~sep:";" fmt l
46+
pp_collection ~pp_elm:pp_repr ~open_:"(" ~close:")" ~sep:"," fmt l
47+
| List l -> pp_collection ~pp_elm:pp_repr ~open_:"[" ~close:"]" ~sep:";" fmt l
6748
| Record fields ->
6849
pp_collection ~pp_elm:pp_field ~open_:"{" ~close:"}" ~sep:";" fmt fields
6950
| Constr (cname, []) -> Format.fprintf fmt "%s" cname
7051
| Constr (cname, [ (Constr (_, _ :: _) as x) ]) ->
71-
Format.fprintf fmt "@[<hv 2>%s@ (%a)@]" cname pp_simple_val x
52+
Format.fprintf fmt "@[<hv 2>%s@ (%a)@]" cname pp_repr x
7253
| Constr (cname, [ x ]) ->
73-
Format.fprintf fmt "@[<hv 2>%s@ %a@]" cname pp_simple_val x
54+
Format.fprintf fmt "@[<hv 2>%s@ %a@]" cname pp_repr x
7455
| Constr (cname, l) ->
75-
Format.fprintf fmt "@[<hv 2>%s@ %a@]" cname pp_simple_val (Tuple l)
56+
Format.fprintf fmt "@[<hv 2>%s@ %a@]" cname pp_repr (Tuple l)
7657

77-
and pp_field fmt (fname, simple_val) =
78-
Format.fprintf fmt "@[<hv 2>%s =@ %a@]" fname pp_simple_val simple_val
58+
and pp_field fmt (fname, repr) =
59+
Format.fprintf fmt "@[<hv 2>%s =@ %a@]" fname pp_repr repr
7960

80-
class lift_simple_val =
61+
(* TODO: split into Printer and Lifter config*)
62+
module Config = struct
63+
type loc_mode = [ `Short | `Full ]
64+
65+
type t = {
66+
show_attrs : bool;
67+
show_locs : bool;
68+
loc_mode : loc_mode;
69+
printer : repr pp;
70+
}
71+
72+
module Default = struct
73+
let show_attrs = false
74+
let show_locs = false
75+
let loc_mode = `Short
76+
let printer = pp_repr
77+
end
78+
79+
let default =
80+
let open Default in
81+
{ show_attrs; show_locs; loc_mode; printer = pp_repr }
82+
83+
let make ?(show_attrs = Default.show_attrs) ?(show_locs = Default.show_locs)
84+
?(loc_mode = Default.loc_mode) ?(printer = Default.printer) () =
85+
{ show_attrs; show_locs; loc_mode; printer }
86+
end
87+
88+
let cnum (pos : Lexing.position) = pos.pos_cnum - pos.pos_bol
89+
90+
class lift_repr =
8191
object (self)
82-
inherit [simple_val] Ast_traverse.lift as super
92+
inherit [repr] Ast_traverse.lift as super
8393
val mutable config = Config.default
8494
method set_config new_config = config <- new_config
8595
method get_config () = config
@@ -139,12 +149,12 @@ class lift_simple_val =
139149

140150
method lift_record_with_desc :
141151
'record 'desc.
142-
lift_desc:('desc -> simple_val) ->
143-
lift_record:('record -> simple_val) ->
152+
lift_desc:('desc -> repr) ->
153+
lift_record:('record -> repr) ->
144154
desc:'desc ->
145155
attrs:attributes ->
146156
'record ->
147-
simple_val =
157+
repr =
148158
fun ~lift_desc ~lift_record ~desc ~attrs x ->
149159
match (config.show_locs, config.show_attrs, attrs) with
150160
| false, false, _ | false, true, [] -> lift_desc desc
@@ -302,44 +312,43 @@ class lift_simple_val =
302312
| NoInjectivity -> Constr ("NoInjectivity", [])
303313
end
304314

305-
type 'a pp = Format.formatter -> 'a -> unit
306315
type 'a configurable = ?config:Config.t -> 'a pp
307316
type 'a configured = 'a pp
308317

309318
module type S = sig
310-
type 'a printer
311-
312-
val structure : structure printer
313-
val structure_item : structure_item printer
314-
val signature : signature printer
315-
val signature_item : signature_item printer
316-
val expression : expression printer
317-
val pattern : pattern printer
318-
val core_type : core_type printer
319+
type 'a ast_printer
320+
321+
val structure : structure ast_printer
322+
val structure_item : structure_item ast_printer
323+
val signature : signature ast_printer
324+
val signature_item : signature_item ast_printer
325+
val expression : expression ast_printer
326+
val pattern : pattern ast_printer
327+
val core_type : core_type ast_printer
319328
end
320329

321330
module type Conf = sig
322331
val config : Config.t
323332
end
324333

325-
module type Configured = S with type 'a printer = 'a configured
326-
module type Configurable = S with type 'a printer = 'a configurable
334+
module type Configured = S with type 'a ast_printer = 'a configured
335+
module type Configurable = S with type 'a ast_printer = 'a configurable
327336

328337
module Make (Conf : Conf) : Configured = struct
329-
type 'a printer = 'a configured
338+
type 'a ast_printer = 'a configured
330339

331340
let lsv =
332-
let lift_simple_val = new lift_simple_val in
333-
lift_simple_val#set_config Conf.config;
334-
lift_simple_val
335-
336-
let structure fmt str = pp_simple_val fmt (lsv#structure str)
337-
let structure_item fmt str = pp_simple_val fmt (lsv#structure_item str)
338-
let signature fmt str = pp_simple_val fmt (lsv#signature str)
339-
let signature_item fmt str = pp_simple_val fmt (lsv#signature_item str)
340-
let expression fmt str = pp_simple_val fmt (lsv#expression str)
341-
let pattern fmt str = pp_simple_val fmt (lsv#pattern str)
342-
let core_type fmt str = pp_simple_val fmt (lsv#core_type str)
341+
let lift_repr = new lift_repr in
342+
lift_repr#set_config Conf.config;
343+
lift_repr
344+
345+
let structure fmt str = pp_repr fmt (lsv#structure str)
346+
let structure_item fmt str = pp_repr fmt (lsv#structure_item str)
347+
let signature fmt str = pp_repr fmt (lsv#signature str)
348+
let signature_item fmt str = pp_repr fmt (lsv#signature_item str)
349+
let expression fmt str = pp_repr fmt (lsv#expression str)
350+
let pattern fmt str = pp_repr fmt (lsv#pattern str)
351+
let core_type fmt str = pp_repr fmt (lsv#core_type str)
343352
end
344353

345354
let make config =
@@ -351,25 +360,25 @@ module Default = Make (struct
351360
let config = Config.default
352361
end)
353362

354-
type 'a printer = 'a configurable
363+
type 'a ast_printer = 'a configurable
355364

356-
let lift_simple_val = new lift_simple_val
365+
let lift_repr = new lift_repr
357366

358367
let with_config ~config ~f =
359-
let old_config = lift_simple_val#get_config () in
360-
lift_simple_val#set_config config;
368+
let old_config = lift_repr#get_config () in
369+
lift_repr#set_config config;
361370
let res = f () in
362-
lift_simple_val#set_config old_config;
371+
lift_repr#set_config old_config;
363372
res
364373

365-
let pp_with_config (type a) (lifter : a -> simple_val)
366-
?(config = Config.default) fmt (x : a) =
367-
with_config ~config ~f:(fun () -> pp_simple_val fmt (lifter x))
368-
369-
let structure = pp_with_config lift_simple_val#structure
370-
let structure_item = pp_with_config lift_simple_val#structure_item
371-
let signature = pp_with_config lift_simple_val#signature
372-
let signature_item = pp_with_config lift_simple_val#signature_item
373-
let expression = pp_with_config lift_simple_val#expression
374-
let pattern = pp_with_config lift_simple_val#pattern
375-
let core_type = pp_with_config lift_simple_val#core_type
374+
let pp_with_config (type a) (lifter : a -> repr) ?(config = Config.default) fmt
375+
(x : a) =
376+
with_config ~config ~f:(fun () -> config.printer fmt (lifter x))
377+
378+
let structure = pp_with_config lift_repr#structure
379+
let structure_item = pp_with_config lift_repr#structure_item
380+
let signature = pp_with_config lift_repr#signature
381+
let signature_item = pp_with_config lift_repr#signature_item
382+
let expression = pp_with_config lift_repr#expression
383+
let pattern = pp_with_config lift_repr#pattern
384+
let core_type = pp_with_config lift_repr#core_type

0 commit comments

Comments
 (0)