Skip to content

Commit 78d3a43

Browse files
committed
upgrade ppxlib to 0.36 / handle Ptyp_open
1 parent 4838a99 commit 78d3a43

File tree

2 files changed

+150
-3
lines changed

2 files changed

+150
-3
lines changed

ppx/native/common/ppx_deriving_tools.ml

+48-3
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,35 @@ open Ast_builder.Default
44
open StdLabels
55
open Expansion_helpers
66

7+
module Lid = struct
8+
let flatten =
9+
let rec flat accu = function
10+
| Lident s -> s :: accu
11+
| Ldot (lid, s) -> flat (s :: accu) lid
12+
| Lapply (_, _) -> failwith "Longident.flat"
13+
in
14+
fun lid -> flat [] lid
15+
16+
let unflatten l =
17+
match l with
18+
| [] -> None
19+
| hd :: tl ->
20+
Some
21+
(List.fold_left
22+
~f:(fun p s -> Ldot (p, s))
23+
~init:(Lident hd) tl)
24+
end
25+
726
let not_supported ~loc what =
827
Location.raise_errorf ~loc "%s are not supported" what
928

1029
let map_loc f a_loc = { a_loc with txt = f a_loc.txt }
1130

31+
let lident_with_optional_open ?opn label =
32+
match opn with
33+
| Some { txt = lid; _ } -> Longident.Ldot (lid, label)
34+
| None -> lident label
35+
1236
let gen_bindings ~loc prefix n =
1337
List.split
1438
(List.init ~len:n ~f:(fun i ->
@@ -129,13 +153,14 @@ module Schema = struct
129153
| Rinherit _ ->
130154
not_supported ~loc:field.prf_loc "this polyvariant inherit"
131155

132-
let repr_core_type ty =
156+
let rec repr_core_type ty =
133157
let loc = ty.ptyp_loc in
134158
match ty.ptyp_desc with
135159
| Ptyp_tuple ts -> `Ptyp_tuple ts
136160
| Ptyp_constr (id, ts) -> `Ptyp_constr (id, ts)
137161
| Ptyp_var txt -> `Ptyp_var { txt; loc = ty.ptyp_loc }
138162
| Ptyp_variant (fs, Closed, None) -> `Ptyp_variant fs
163+
| Ptyp_open (id, ct) -> `Ptyp_open (id, repr_core_type ct)
139164
| Ptyp_variant _ -> not_supported ~loc "non closed polyvariants"
140165
| Ptyp_arrow _ -> not_supported ~loc "function types"
141166
| Ptyp_any -> not_supported ~loc "type placeholders"
@@ -246,11 +271,31 @@ module Schema = struct
246271

247272
method private derive_of_core_type' t =
248273
let loc = t.ptyp_loc in
249-
match repr_core_type t with
274+
self#derive_of_core_type_repr ~loc t (repr_core_type t)
275+
276+
method private derive_of_core_type_repr ?opn ~loc t repr =
277+
match repr with
250278
| `Ptyp_tuple ts -> As_fun (self#derive_of_tuple t ts)
251279
| `Ptyp_var label ->
252-
As_val (ederiver self#name (map_loc lident label))
280+
As_val
281+
(ederiver self#name
282+
(map_loc (lident_with_optional_open ?opn) label))
283+
| `Ptyp_open (_, `Ptyp_open _) -> assert false
284+
| `Ptyp_open (lid, ct) ->
285+
self#derive_of_core_type_repr ~opn:lid ~loc t ct
253286
| `Ptyp_constr (id, ts) ->
287+
let id =
288+
match opn with
289+
| Some { txt = lid; loc } ->
290+
{
291+
txt =
292+
Lid.flatten lid @ Lid.flatten id.txt
293+
|> Lid.unflatten
294+
|> Option.get;
295+
loc;
296+
}
297+
| None -> id
298+
in
254299
self#derive_type_ref' self#name ~loc id ts
255300
| `Ptyp_variant fs -> As_fun (self#derive_of_polyvariant t fs)
256301

ppx/test/ptype_open.t

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
We can use the `Ptyp_open` AST node:
2+
$ echo '
3+
> module X = struct
4+
> type x = (int * int) [@@deriving json]
5+
> end
6+
> type u = X.(x) [@@deriving json]
7+
> let () = print_endline (Ppx_deriving_json_runtime.to_string (u_to_json (1, 2)))
8+
> let () = assert (u_of_json (Ppx_deriving_json_runtime.of_string {|[1, 2]|}) = (1, 2))
9+
> ' | ./run.sh
10+
=== ppx output:native ===
11+
module X =
12+
struct
13+
type x = (int * int)[@@deriving json]
14+
include
15+
struct
16+
let _ = fun (_ : x) -> ()
17+
[@@@ocaml.warning "-39-11-27"]
18+
let rec x_of_json =
19+
(fun x ->
20+
match x with
21+
| `List (x_0::x_1::[]) -> ((int_of_json x_0), (int_of_json x_1))
22+
| _ ->
23+
Ppx_deriving_json_runtime.of_json_error ~json:x
24+
"expected a JSON array of length 2" : Yojson.Basic.t -> x)
25+
let _ = x_of_json
26+
[@@@ocaml.warning "-39-11-27"]
27+
let rec x_to_json =
28+
(fun x ->
29+
match x with
30+
| (x_0, x_1) -> `List [int_to_json x_0; int_to_json x_1] :
31+
x -> Yojson.Basic.t)
32+
let _ = x_to_json
33+
end[@@ocaml.doc "@inline"][@@merlin.hide ]
34+
end
35+
type u = X.(x)[@@deriving json]
36+
include
37+
struct
38+
let _ = fun (_ : u) -> ()
39+
[@@@ocaml.warning "-39-11-27"]
40+
let rec u_of_json = (fun x -> X.x_of_json x : Yojson.Basic.t -> u)
41+
let _ = u_of_json
42+
[@@@ocaml.warning "-39-11-27"]
43+
let rec u_to_json = (fun x -> X.x_to_json x : u -> Yojson.Basic.t)
44+
let _ = u_to_json
45+
end[@@ocaml.doc "@inline"][@@merlin.hide ]
46+
let () =
47+
print_endline (Ppx_deriving_json_runtime.to_string (u_to_json (1, 2)))
48+
let () =
49+
assert
50+
((u_of_json (Ppx_deriving_json_runtime.of_string {|[1, 2]|})) = (1, 2))
51+
=== ppx output:browser ===
52+
module X =
53+
struct
54+
type x = (int * int)[@@deriving json]
55+
include
56+
struct
57+
let _ = fun (_ : x) -> ()
58+
[@@@ocaml.warning "-39-11-27"]
59+
let rec x_of_json =
60+
(fun x ->
61+
if
62+
Stdlib.(&&) (Js.Array.isArray x)
63+
(Stdlib.(=)
64+
(Js.Array.length (Obj.magic x : Js.Json.t array)) 2)
65+
then
66+
let es = (Obj.magic x : Js.Json.t array) in
67+
((int_of_json (Js.Array.unsafe_get es 0)),
68+
(int_of_json (Js.Array.unsafe_get es 1)))
69+
else
70+
Ppx_deriving_json_runtime.of_json_error ~json:x
71+
"expected a JSON array of length 2" : Js.Json.t -> x)
72+
let _ = x_of_json
73+
[@@@ocaml.warning "-39-11-27"]
74+
let rec x_to_json =
75+
(fun x ->
76+
match x with
77+
| (x_0, x_1) ->
78+
(Obj.magic [|(int_to_json x_0);(int_to_json x_1)|] :
79+
Js.Json.t) : x -> Js.Json.t)
80+
let _ = x_to_json
81+
end[@@ocaml.doc "@inline"][@@merlin.hide ]
82+
end
83+
type u = X.(x)[@@deriving json]
84+
include
85+
struct
86+
let _ = fun (_ : u) -> ()
87+
[@@@ocaml.warning "-39-11-27"]
88+
let rec u_of_json = (fun x -> X.x_of_json x : Js.Json.t -> u)
89+
let _ = u_of_json
90+
[@@@ocaml.warning "-39-11-27"]
91+
let rec u_to_json = (fun x -> X.x_to_json x : u -> Js.Json.t)
92+
let _ = u_to_json
93+
end[@@ocaml.doc "@inline"][@@merlin.hide ]
94+
let () =
95+
print_endline (Ppx_deriving_json_runtime.to_string (u_to_json (1, 2)))
96+
let () =
97+
assert
98+
((u_of_json (Ppx_deriving_json_runtime.of_string {|[1, 2]|})) = (1, 2))
99+
=== stdout:native ===
100+
[1,2]
101+
=== stdout:js ===
102+
[1,2]

0 commit comments

Comments
 (0)