@@ -56,6 +56,10 @@ let rec checkNotFunciton (ty : Parsetree.core_type) =
5656 | Ptyp_extension _ -> ()
5757
5858
59+ let get_optional_attrs =
60+ [Ast_attributes. bs_get; Ast_attributes. bs_return_undefined]
61+ let get_attrs = [ Ast_attributes. bs_get ]
62+ let set_attrs = [Ast_attributes. bs_set]
5963let handleTdcl (tdcl : Parsetree.type_declaration ) =
6064 let core_type = U. core_type_of_type_declaration tdcl in
6165 let loc = tdcl.ptype_loc in
@@ -68,59 +72,83 @@ let handleTdcl (tdcl : Parsetree.type_declaration) =
6872 } in
6973 match tdcl.ptype_kind with
7074 | Ptype_record label_declarations ->
71- let setter_accessor =
72- Ext_list. fold_right (fun
73- ({pld_name = {txt = label_name ; loc = label_loc } as pld_name ;
75+ let is_private = tdcl.ptype_private = Private in
76+ let has_optional_field =
77+ List. exists (fun ({pld_type} : Parsetree.label_declaration ) ->
78+ Ast_core_type. is_user_option pld_type
79+ ) label_declarations in
80+ let setter_accessor, makeType, labels =
81+ Ext_list. fold_right
82+ (fun
83+ ({pld_name =
84+ {txt = label_name ; loc = label_loc } as pld_name ;
7485 pld_type;
7586 pld_mutable;
76- pld_attributes
77- } :
78- Parsetree. label_declaration ) acc ->
87+ pld_attributes;
88+ pld_loc
89+ } :
90+ Parsetree. label_declaration ) (acc , maker , labels ) ->
7991 let () = checkNotFunciton pld_type in
80- let prim =
92+ (* TODO: explain why *)
93+ let prim, newLabel =
8194 match Ast_attributes. iter_process_bs_string_as pld_attributes with
82- | None -> [label_name]
83- | Some new_name -> [new_name]
95+ | None ->
96+ [label_name], pld_name
97+ | Some new_name ->
98+ [new_name], {pld_name with txt = new_name}
8499 in
85- let getter =
86- Val. mk
87- pld_name (* we always use this: it is fixed in ocaml API*)
88- ~attrs: [Ast_attributes. bs_get]
89- ~prim
90- (Typ. arrow " " core_type pld_type) :: acc in
91- match pld_mutable with
92- | Mutable ->
93- Val. mk
94- {loc = label_loc; txt = label_name ^ " Set" }
95- (* setter *)
96- ~attrs: [Ast_attributes. bs_set]
97- ~prim
98- (Typ. arrow " " core_type (Typ. arrow " " pld_type (Ast_literal. type_unit () ))) :: getter
99- | Immutable -> getter
100- ) label_declarations []
100+ let is_option = Ast_core_type. is_user_option pld_type in
101+ let getter_type =
102+ Typ. arrow ~loc " " core_type pld_type in
103+ let acc =
104+ Val. mk pld_name
105+ ~attrs: (
106+ if is_option then get_optional_attrs
107+ else get_attrs)
108+ ~prim getter_type :: acc in
109+ let is_current_field_mutable = pld_mutable = Mutable in
110+ let acc =
111+ if is_current_field_mutable then
112+ let setter_type =
113+ (Typ. arrow " " core_type
114+ (Typ. arrow " "
115+ (if is_option then
116+ Ast_core_type. extract_option_type_exn pld_type
117+ else pld_type)
118+ (Ast_literal. type_unit () ))) in
119+ Val. mk
120+ {loc = label_loc; txt = label_name ^ " Set" }
121+ (* setter *)
122+ ~attrs: set_attrs
123+ ~prim setter_type
124+ :: acc
125+ else acc in
126+ acc,
127+ (if is_option then
128+ Ast_core_type. opt_arrow pld_loc label_name pld_type maker
129+ else Typ. arrow ~loc: pld_loc label_name pld_type maker
130+ ),
131+ (is_option, newLabel)::labels
132+ ) label_declarations
133+ ([] ,
134+ (if has_optional_field then
135+ Typ. arrow ~loc " " (Ast_literal. type_unit () ) core_type
136+ else core_type),
137+ [] )
101138 in
102139 newTdcl,
103- (match tdcl.ptype_private with
104- | Private -> setter_accessor
105- | Public ->
106- let ty =
107- Ext_list. fold_right (fun ({pld_name = {txt} ; pld_type} : Parsetree.label_declaration ) acc ->
108- Typ. arrow txt pld_type acc
109- ) label_declarations core_type in
140+ (if is_private then
141+ setter_accessor
142+ else
110143 let myPrims =
111- External_process. pval_prim_of_labels
112- (List. map
113- (fun ({pld_name; pld_attributes} : Parsetree.label_declaration ) ->
114- match Ast_attributes. iter_process_bs_string_as pld_attributes with
115- | None -> pld_name
116- | Some new_name -> {pld_name with txt = new_name}
117- )
118- label_declarations)
119- in
144+ External_process. pval_prim_of_option_labels
145+ labels
146+ has_optional_field
147+ in
120148 let myMaker =
121- Val. mk ~loc
122- {loc; txt = type_name}
123- ~prim: myPrims ty in
149+ Val. mk ~loc
150+ {loc; txt = type_name}
151+ ~prim: myPrims makeType in
124152 (myMaker :: setter_accessor))
125153
126154 | Ptype_abstract
0 commit comments