@@ -5,13 +5,28 @@ open Parsetree
55open Ast_helper
66open Ast_convenience
77
8+ module StringSet = Ppx_deriving. StringSet
9+
810let deriver = " eq"
911let raise_errorf = Ppx_deriving. raise_errorf
1012
13+ type eq_options =
14+ {
15+ allow_std_type_shadowing : bool ;
16+ }
17+
18+ let default_eq_options =
19+ {
20+ allow_std_type_shadowing= false ;
21+ }
22+
1123let parse_options options =
12- options |> List. iter ( fun ( name , expr ) ->
24+ let option_parser acc ( name , expr ) =
1325 match name with
14- | _ -> raise_errorf ~loc: expr.pexp_loc " %s does not support option %s" deriver name)
26+ | "allow_std_type_shadowing" -> { allow_std_type_shadowing = true }
27+ | _ ->
28+ raise_errorf ~loc: expr.pexp_loc " %s does not support option %s" deriver name in
29+ List. fold_left option_parser default_eq_options options
1530
1631let attr_equal attrs =
1732 Ppx_deriving. (attrs |> attr ~deriver " equal" |> Arg. (get_attr ~deriver expr))
@@ -23,58 +38,63 @@ let pattn side typs =
2338 List. mapi (fun i _ -> pvar (argn side i)) typs
2439
2540let core_type_of_decl ~options ~path type_decl =
26- parse_options options;
41+ ignore ( parse_options options) ;
2742 let typ = Ppx_deriving. core_type_of_type_decl type_decl in
2843 Ppx_deriving. poly_arrow_of_type_decl
2944 (fun var -> [% type : [% t var] -> [% t var] -> bool ])
3045 type_decl
3146 [% type : [% t typ] -> [% t typ] -> bool ]
3247
3348let sig_of_type ~options ~path type_decl =
34- parse_options options;
49+ ignore ( parse_options options) ;
3550 [Sig. value (Val. mk (mknoloc (Ppx_deriving. mangle_type_decl (`Prefix " equal" ) type_decl))
3651 (core_type_of_decl ~options ~path type_decl))]
3752
38- let rec exprsn typs =
53+ let rec exprsn group_def typs =
3954 typs |> List. mapi (fun i typ ->
40- app (expr_of_typ typ) [evar (argn `lhs i); evar (argn `rhs i)])
55+ app (expr_of_typ group_def typ) [evar (argn `lhs i); evar (argn `rhs i)])
4156
42- and expr_of_typ typ =
57+ and expr_of_typ group_def typ =
4358 match attr_equal typ.ptyp_attributes with
4459 | Some fn -> fn
4560 | None ->
4661 match typ with
62+ | { ptyp_desc = Ptyp_constr ({ txt = (Lident id as lid) }, args) }
63+ when StringSet. mem id group_def ->
64+ let equal_fn = Exp. ident (mknoloc (Ppx_deriving. mangle_lid (`Prefix " equal" ) lid)) in
65+ app equal_fn (List. map (expr_of_typ group_def) args)
4766 | [% type : _] | [% type : unit ] -> [% expr fun _ _ -> true ]
4867 | [% type : int ] | [% type : int32 ] | [% type : Int32. t]
4968 | [% type : int64 ] | [% type : Int64. t] | [% type : nativeint ] | [% type : Nativeint. t]
50- | [% type : float ] | [% type : bool ] | [% type : char ] | [% type : string ] | [% type : bytes] ->
69+ | [% type : float ] | [% type : bool ] | [% type : char ] | [% type : string ] |
70+ [% type : String. t] | [% type : bytes] ->
5171 [% expr (fun (a :[%t typ] ) b -> a = b)]
52- | [% type : [% t? typ] ref ] -> [% expr fun a b -> [% e expr_of_typ typ] ! a ! b]
72+ | [% type : [% t? typ] ref ] -> [% expr fun a b -> [% e expr_of_typ group_def typ] ! a ! b]
5373 | [% type : [% t? typ] list ] ->
5474 [% expr
5575 let rec loop x y =
5676 match x, y with
5777 | [] , [] -> true
58- | a :: x , b :: y -> [% e expr_of_typ typ] a b && loop x y
78+ | a :: x , b :: y -> [% e expr_of_typ group_def typ] a b && loop x y
5979 | _ -> false
6080 in (fun x y -> loop x y)]
6181 | [% type : [% t? typ] array ] ->
6282 [% expr fun x y ->
6383 let rec loop i =
64- (i = Array. length x || [% e expr_of_typ typ] x.(i) y.(i)) && loop (i + 1 )
84+ (i = Array. length x || [% e expr_of_typ group_def typ] x.(i) y.(i)) && loop (i + 1 )
6585 in Array. length x = Array. length y && loop 0 ]
6686 | [% type : [% t? typ] option ] ->
6787 [% expr fun x y ->
6888 match x, y with
6989 | None , None -> true
70- | Some a , Some b -> [% e expr_of_typ typ] a b
90+ | Some a , Some b -> [% e expr_of_typ group_def typ] a b
7191 | _ -> false ]
7292 | { ptyp_desc = Ptyp_constr ({ txt = lid } , args ) } ->
7393 let equal_fn = Exp. ident (mknoloc (Ppx_deriving. mangle_lid (`Prefix " equal" ) lid)) in
74- app equal_fn (List. map expr_of_typ args)
94+ app equal_fn (List. map ( expr_of_typ group_def) args)
7595 | { ptyp_desc = Ptyp_tuple typs } ->
7696 [% expr fun [%p ptuple (pattn `lhs typs )] [%p ptuple (pattn `rhs typs )] ->
77- [% e exprsn typs |> Ppx_deriving. (fold_exprs (binop_reduce [% expr (&& )]))]]
97+ [% e exprsn group_def typs |> Ppx_deriving. (fold_exprs (binop_reduce [% expr (&& )]))]]
7898 | { ptyp_desc = Ptyp_variant (fields , _ , _ ); ptyp_loc } ->
7999 let cases =
80100 (fields |> List. map (fun field ->
@@ -84,42 +104,44 @@ and expr_of_typ typ =
84104 Exp. case (pdup (fun _ -> Pat. variant label None )) [% expr true ]
85105 | Rtag (label , _ , false , [typ ]) ->
86106 Exp. case (pdup (fun var -> Pat. variant label (Some (pvar var))))
87- (app (expr_of_typ typ) [evar " lhs" ; evar " rhs" ])
107+ (app (expr_of_typ group_def typ) [evar " lhs" ; evar " rhs" ])
88108 | Rinherit ({ ptyp_desc = Ptyp_constr (tname , _ ) } as typ ) ->
89109 Exp. case (pdup (fun var -> Pat. alias (Pat. type_ tname) (mknoloc var)))
90- (app (expr_of_typ typ) [evar " lhs" ; evar " rhs" ])
110+ (app (expr_of_typ group_def typ) [evar " lhs" ; evar " rhs" ])
91111 | _ ->
92112 raise_errorf ~loc: ptyp_loc " %s cannot be derived for %s"
93113 deriver (Ppx_deriving. string_of_core_type typ))) @
94114 [Exp. case (pvar " _" ) [% expr false ]]
95115 in
96116 [% expr fun lhs rhs -> [% e Exp. match_ [% expr lhs, rhs] cases]]
97117 | { ptyp_desc = Ptyp_var name } -> evar (" poly_" ^ name)
98- | { ptyp_desc = Ptyp_alias (typ , _ ) } -> expr_of_typ typ
118+ | { ptyp_desc = Ptyp_alias (typ , _ ) } -> expr_of_typ group_def typ
99119 | { ptyp_loc } ->
100120 raise_errorf ~loc: ptyp_loc " %s cannot be derived for %s"
101121 deriver (Ppx_deriving. string_of_core_type typ)
102122
103- let str_of_type ~options ~path ({ ptype_loc = loc } as type_decl ) =
104- parse_options options;
123+ let str_of_type ~options ~path group_def ({ ptype_loc = loc } as type_decl ) =
124+ ignore ( parse_options options) ;
105125 let comparator =
106126 match type_decl.ptype_kind, type_decl.ptype_manifest with
107- | Ptype_abstract , Some manifest -> expr_of_typ manifest
127+ | Ptype_abstract , Some manifest -> expr_of_typ group_def manifest
108128 | Ptype_variant constrs , _ ->
129+ let wildcard = match constrs with
130+ | [] | [_] -> []
131+ | _ :: _ :: _ -> [Exp. case (pvar " _" ) [% expr false ]] in
109132 let cases =
110133 (constrs |> List. map (fun { pcd_name = { txt = name } ; pcd_args = typs } ->
111- exprsn typs |>
134+ exprsn group_def typs |>
112135 Ppx_deriving. (fold_exprs ~unit: [% expr true ] (binop_reduce [% expr (&& )])) |>
113136 Exp. case (ptuple [pconstr name (pattn `lhs typs);
114- pconstr name (pattn `rhs typs)]))) @
115- [Exp. case (pvar " _" ) [% expr false ]]
137+ pconstr name (pattn `rhs typs)]))) @ wildcard
116138 in
117139 [% expr fun lhs rhs -> [% e Exp. match_ [% expr lhs, rhs] cases]]
118140 | Ptype_record labels , _ ->
119141 let exprs =
120142 labels |> List. map (fun { pld_name = { txt = name } ; pld_type } ->
121143 let field obj = Exp. field obj (mknoloc (Lident name)) in
122- app (expr_of_typ pld_type) [field (evar " lhs" ); field (evar " rhs" )])
144+ app (expr_of_typ group_def pld_type) [field (evar " lhs" ); field (evar " rhs" )])
123145 in
124146 [% expr fun lhs rhs -> [% e exprs |> Ppx_deriving. (fold_exprs (binop_reduce [% expr (&& )]))]]
125147 | Ptype_abstract , None ->
@@ -135,11 +157,26 @@ let str_of_type ~options ~path ({ ptype_loc = loc } as type_decl) =
135157 pvar (Ppx_deriving. mangle_type_decl (`Prefix " equal" ) type_decl) in
136158 [Vb. mk (Pat. constraint_ eq_var out_type) (polymorphize comparator)]
137159
160+ let type_decl_str ~options ~path type_decls =
161+ let opts = parse_options options in
162+ let typename_set =
163+ Ppx_deriving. extract_typename_of_type_group
164+ deriver
165+ ~allow_shadowing: opts.allow_std_type_shadowing
166+ type_decls in
167+ let here_loc = (List. hd type_decls).ptype_loc in
168+ if StringSet. mem " bool" typename_set then
169+ raise_errorf
170+ ~loc: here_loc
171+ " %s can't derivate types when shadowing bool (even with option)" deriver;
172+ let code =
173+ List. map (str_of_type ~options ~path typename_set) type_decls in
174+ [Str. value Recursive (List. concat code)]
175+
138176let () =
139- Ppx_deriving. (register (create " eq"
140- ~core_type: expr_of_typ
141- ~type_decl_str: (fun ~options ~path type_decls ->
142- [Str. value Recursive (List. concat (List. map (str_of_type ~options ~path ) type_decls))])
177+ Ppx_deriving. (register (create deriver
178+ ~core_type: (expr_of_typ StringSet. empty)
179+ ~type_decl_str: type_decl_str
143180 ~type_decl_sig: (fun ~options ~path type_decls ->
144181 List. concat (List. map (sig_of_type ~options ~path ) type_decls))
145182 ()
0 commit comments