@@ -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_masking : bool ;
16+ }
17+
18+ let default_eq_options =
19+ {
20+ allow_std_type_masking = 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_masking" -> { allow_std_type_masking = 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,62 @@ 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
29- (fun var -> [% type : [% t var] -> [% t var] -> bool ])
44+ (fun var -> [% type : [% t var] -> [% t var] -> Pervasives. bool ])
3045 type_decl
31- [% type : [% t typ] -> [% t typ] -> bool ]
46+ [% type : [% t typ] -> [% t typ] -> Pervasives. 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]
5069 | [% type : float ] | [% type : bool ] | [% type : char ] | [% type : string ] | [% type : bytes] ->
5170 [% expr (fun (a :[%t typ] ) b -> a = b)]
52- | [% type : [% t? typ] ref ] -> [% expr fun a b -> [% e expr_of_typ typ] ! a ! b]
71+ | [% type : [% t? typ] ref ] -> [% expr fun a b -> [% e expr_of_typ group_def typ] ! a ! b]
5372 | [% type : [% t? typ] list ] ->
5473 [% expr
5574 let rec loop x y =
5675 match x, y with
5776 | [] , [] -> true
58- | a :: x , b :: y -> [% e expr_of_typ typ] a b && loop x y
77+ | a :: x , b :: y -> [% e expr_of_typ group_def typ] a b && loop x y
5978 | _ -> false
6079 in (fun x y -> loop x y)]
6180 | [% type : [% t? typ] array ] ->
6281 [% expr fun x y ->
6382 let rec loop i =
64- (i = Array. length x || [% e expr_of_typ typ] x.(i) y.(i)) && loop (i + 1 )
83+ (i = Array. length x || [% e expr_of_typ group_def typ] x.(i) y.(i)) && loop (i + 1 )
6584 in Array. length x = Array. length y && loop 0 ]
6685 | [% type : [% t? typ] option ] ->
6786 [% expr fun x y ->
6887 match x, y with
6988 | None , None -> true
70- | Some a , Some b -> [% e expr_of_typ typ] a b
89+ | Some a , Some b -> [% e expr_of_typ group_def typ] a b
7190 | _ -> false ]
7291 | { ptyp_desc = Ptyp_constr ({ txt = lid } , args ) } ->
7392 let equal_fn = Exp. ident (mknoloc (Ppx_deriving. mangle_lid (`Prefix " equal" ) lid)) in
74- app equal_fn (List. map expr_of_typ args)
93+ app equal_fn (List. map ( expr_of_typ group_def) args)
7594 | { ptyp_desc = Ptyp_tuple typs } ->
7695 [% expr fun [%p ptuple (pattn `lhs typs )] [%p ptuple (pattn `rhs typs )] ->
77- [% e exprsn typs |> Ppx_deriving. (fold_exprs (binop_reduce [% expr (&& )]))]]
96+ [% e exprsn group_def typs |> Ppx_deriving. (fold_exprs (binop_reduce [% expr (&& )]))]]
7897 | { ptyp_desc = Ptyp_variant (fields , _ , _ ); ptyp_loc } ->
7998 let cases =
8099 (fields |> List. map (fun field ->
@@ -84,42 +103,44 @@ and expr_of_typ typ =
84103 Exp. case (pdup (fun _ -> Pat. variant label None )) [% expr true ]
85104 | Rtag (label , _ , false , [typ ]) ->
86105 Exp. case (pdup (fun var -> Pat. variant label (Some (pvar var))))
87- (app (expr_of_typ typ) [evar " lhs" ; evar " rhs" ])
106+ (app (expr_of_typ group_def typ) [evar " lhs" ; evar " rhs" ])
88107 | Rinherit ({ ptyp_desc = Ptyp_constr (tname , _ ) } as typ ) ->
89108 Exp. case (pdup (fun var -> Pat. alias (Pat. type_ tname) (mknoloc var)))
90- (app (expr_of_typ typ) [evar " lhs" ; evar " rhs" ])
109+ (app (expr_of_typ group_def typ) [evar " lhs" ; evar " rhs" ])
91110 | _ ->
92111 raise_errorf ~loc: ptyp_loc " %s cannot be derived for %s"
93112 deriver (Ppx_deriving. string_of_core_type typ))) @
94113 [Exp. case (pvar " _" ) [% expr false ]]
95114 in
96115 [% expr fun lhs rhs -> [% e Exp. match_ [% expr lhs, rhs] cases]]
97116 | { ptyp_desc = Ptyp_var name } -> evar (" poly_" ^ name)
98- | { ptyp_desc = Ptyp_alias (typ , _ ) } -> expr_of_typ typ
117+ | { ptyp_desc = Ptyp_alias (typ , _ ) } -> expr_of_typ group_def typ
99118 | { ptyp_loc } ->
100119 raise_errorf ~loc: ptyp_loc " %s cannot be derived for %s"
101120 deriver (Ppx_deriving. string_of_core_type typ)
102121
103- let str_of_type ~options ~path ({ ptype_loc = loc } as type_decl ) =
104- parse_options options;
122+ let str_of_type ~options ~path group_def ({ ptype_loc = loc } as type_decl ) =
123+ ignore ( parse_options options) ;
105124 let comparator =
106125 match type_decl.ptype_kind, type_decl.ptype_manifest with
107- | Ptype_abstract , Some manifest -> expr_of_typ manifest
126+ | Ptype_abstract , Some manifest -> expr_of_typ group_def manifest
108127 | Ptype_variant constrs , _ ->
128+ let wildcard = match constrs with
129+ | [] | [_] -> []
130+ | _ :: _ :: _ -> [Exp. case (pvar " _" ) [% expr false ]] in
109131 let cases =
110132 (constrs |> List. map (fun { pcd_name = { txt = name } ; pcd_args = typs } ->
111- exprsn typs |>
133+ exprsn group_def typs |>
112134 Ppx_deriving. (fold_exprs ~unit: [% expr true ] (binop_reduce [% expr (&& )])) |>
113135 Exp. case (ptuple [pconstr name (pattn `lhs typs);
114- pconstr name (pattn `rhs typs)]))) @
115- [Exp. case (pvar " _" ) [% expr false ]]
136+ pconstr name (pattn `rhs typs)]))) @ wildcard
116137 in
117138 [% expr fun lhs rhs -> [% e Exp. match_ [% expr lhs, rhs] cases]]
118139 | Ptype_record labels , _ ->
119140 let exprs =
120141 labels |> List. map (fun { pld_name = { txt = name } ; pld_type } ->
121142 let field obj = Exp. field obj (mknoloc (Lident name)) in
122- app (expr_of_typ pld_type) [field (evar " lhs" ); field (evar " rhs" )])
143+ app (expr_of_typ group_def pld_type) [field (evar " lhs" ); field (evar " rhs" )])
123144 in
124145 [% expr fun lhs rhs -> [% e exprs |> Ppx_deriving. (fold_exprs (binop_reduce [% expr (&& )]))]]
125146 | Ptype_abstract , None ->
@@ -135,11 +156,21 @@ let str_of_type ~options ~path ({ ptype_loc = loc } as type_decl) =
135156 pvar (Ppx_deriving. mangle_type_decl (`Prefix " equal" ) type_decl) in
136157 [Vb. mk (Pat. constraint_ eq_var out_type) (polymorphize comparator)]
137158
159+ let type_decl_str ~options ~path type_decls =
160+ let opts = parse_options options in
161+ let typename_set =
162+ Ppx_deriving. extract_typename_of_type_group
163+ deriver
164+ ~allow_shadowing: opts.allow_std_type_masking
165+ type_decls in
166+ let code =
167+ List. map (str_of_type ~options ~path typename_set) type_decls in
168+ [Str. value Recursive (List. concat code)]
169+
138170let () =
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))])
171+ Ppx_deriving. (register (create deriver
172+ ~core_type: (expr_of_typ StringSet. empty)
173+ ~type_decl_str: type_decl_str
143174 ~type_decl_sig: (fun ~options ~path type_decls ->
144175 List. concat (List. map (sig_of_type ~options ~path ) type_decls))
145176 ()
0 commit comments