1
+ (* Copyright (C) 2018 Authors of BuckleScript
2
+ *
3
+ * This program is free software: you can redistribute it and/or modify
4
+ * it under the terms of the GNU Lesser General Public License as published by
5
+ * the Free Software Foundation, either version 3 of the License, or
6
+ * (at your option) any later version.
7
+ *
8
+ * In addition to the permissions granted to you by the LGPL, you may combine
9
+ * or link a "work that uses the Library" with a publicly distributed version
10
+ * of this file to produce a combined library or application, then distribute
11
+ * that combined work under the terms of your choosing, with no requirement
12
+ * to comply with the obligations normally placed on you by section 4 of the
13
+ * LGPL version 3 (or the corresponding section of a later version of the LGPL
14
+ * should you choose to use a later version).
15
+ *
16
+ * This program is distributed in the hope that it will be useful,
17
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ * GNU Lesser General Public License for more details.
20
+ *
21
+ * You should have received a copy of the GNU Lesser General Public License
22
+ * along with this program; if not, write to the Free Software
23
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
24
+ open Ast_helper
25
+ let process_getter_setter ~no ~get ~set
26
+ loc name
27
+ (attrs : Ast_attributes.t )
28
+ (ty : Parsetree.core_type ) acc =
29
+ match Ast_attributes. process_method_attributes_rev attrs with
30
+ | {get = None ; set = None } , _ -> no ty :: acc
31
+ | st , pctf_attributes
32
+ ->
33
+ let get_acc =
34
+ match st.set with
35
+ | Some `No_get -> acc
36
+ | None
37
+ | Some `Get ->
38
+ let lift txt =
39
+ Typ. constr ~loc {txt ; loc} [ty] in
40
+ let (null,undefined) =
41
+ match st with
42
+ | {get = Some (null , undefined ) } -> (null, undefined)
43
+ | {get = None } -> (false , false ) in
44
+ let ty =
45
+ match (null,undefined) with
46
+ | false , false -> ty
47
+ | true , false -> lift Ast_literal.Lid. js_null
48
+ | false , true -> lift Ast_literal.Lid. js_undefined
49
+ | true , true -> lift Ast_literal.Lid. js_null_undefined in
50
+ get ty name pctf_attributes
51
+ :: acc
52
+ in
53
+ if st.set = None then get_acc
54
+ else
55
+ set ty (name ^ Literals. setter_suffix) pctf_attributes
56
+ :: get_acc
57
+
58
+
59
+ let handle_class_type_field self
60
+ ({pctf_loc = loc } as ctf : Parsetree.class_type_field )
61
+ acc =
62
+ match ctf.pctf_desc with
63
+ | Pctf_method
64
+ (name, private_flag, virtual_flag, ty)
65
+ ->
66
+ let no (ty : Parsetree.core_type ) =
67
+ let ty =
68
+ match ty.ptyp_desc with
69
+ | Ptyp_arrow (label, args, body)
70
+ ->
71
+ Ast_util. to_method_type
72
+ ty.ptyp_loc self label args body
73
+
74
+ | Ptyp_poly (strs, {ptyp_desc = Ptyp_arrow (label, args, body);
75
+ ptyp_loc})
76
+ ->
77
+ {ty with ptyp_desc =
78
+ Ptyp_poly (strs,
79
+ Ast_util. to_method_type
80
+ ptyp_loc self label args body )}
81
+ | _ ->
82
+ self.typ self ty
83
+ in
84
+ {ctf with
85
+ pctf_desc =
86
+ Pctf_method (name , private_flag, virtual_flag, ty)}
87
+ in
88
+ let get ty name pctf_attributes =
89
+ {ctf with
90
+ pctf_desc =
91
+ Pctf_method (name ,
92
+ private_flag,
93
+ virtual_flag,
94
+ self.typ self ty
95
+ );
96
+ pctf_attributes} in
97
+ let set ty name pctf_attributes =
98
+ {ctf with
99
+ pctf_desc =
100
+ Pctf_method (name,
101
+ private_flag,
102
+ virtual_flag,
103
+ Ast_util. to_method_type
104
+ loc self " " ty
105
+ (Ast_literal. type_unit ~loc () )
106
+ );
107
+ pctf_attributes} in
108
+ process_getter_setter ~no ~get ~set loc name ctf.pctf_attributes ty acc
109
+
110
+ | Pctf_inherit _
111
+ | Pctf_val _
112
+ | Pctf_constraint _
113
+ | Pctf_attribute _
114
+ | Pctf_extension _ ->
115
+ Bs_ast_mapper. default_mapper.class_type_field self ctf :: acc
116
+
117
+
118
+ (*
119
+ Attributes are very hard to attribute
120
+ (since ptyp_attributes could happen in so many places),
121
+ and write ppx extensions correctly,
122
+ we can only use it locally
123
+ *)
124
+
125
+ let handle_core_type
126
+ ~(super : Bs_ast_mapper.mapper )
127
+ ~(self : Bs_ast_mapper.mapper )
128
+ (ty : Parsetree.core_type )
129
+ record_as_js_object
130
+ =
131
+ match ty with
132
+ | {ptyp_desc = Ptyp_extension ({txt = (" bs.obj" | " obj" )}, PTyp ty)}
133
+ ->
134
+ Ext_ref. non_exn_protect record_as_js_object true
135
+ (fun _ -> self.typ self ty )
136
+ | {ptyp_attributes ;
137
+ ptyp_desc = Ptyp_arrow (label, args, body);
138
+ (* let it go without regard label names,
139
+ it will report error later when the label is not empty
140
+ *)
141
+ ptyp_loc = loc
142
+ } ->
143
+ begin match Ast_attributes. process_attributes_rev ptyp_attributes with
144
+ | `Uncurry , ptyp_attributes ->
145
+ Ast_util. to_uncurry_type loc self label args body
146
+ | `Meth_callback , ptyp_attributes ->
147
+ Ast_util. to_method_callback_type loc self label args body
148
+ | `Method , ptyp_attributes ->
149
+ Ast_util. to_method_type loc self label args body
150
+ | `Nothing , _ ->
151
+ Bs_ast_mapper. default_mapper.typ self ty
152
+ end
153
+ | {
154
+ ptyp_desc = Ptyp_object ( methods, closed_flag) ;
155
+ ptyp_loc = loc
156
+ } ->
157
+ let (+>) attr (typ : Parsetree.core_type ) =
158
+ {typ with ptyp_attributes = attr :: typ .ptyp_attributes} in
159
+ let new_methods =
160
+ Ext_list. fold_right (fun (label , ptyp_attrs , core_type ) acc ->
161
+ let get ty name attrs =
162
+ let attrs, core_type =
163
+ match Ast_attributes. process_attributes_rev attrs with
164
+ | `Nothing , attrs -> attrs, ty (* #1678 *)
165
+ | `Uncurry , attrs ->
166
+ attrs, Ast_attributes. bs +> ty
167
+ | `Method , _
168
+ -> Location. raise_errorf ~loc " bs.get/set conflicts with bs.meth"
169
+ | `Meth_callback , attrs ->
170
+ attrs, Ast_attributes. bs_this +> ty
171
+ in
172
+ name , attrs, self.typ self core_type in
173
+ let set ty name attrs =
174
+ let attrs, core_type =
175
+ match Ast_attributes. process_attributes_rev attrs with
176
+ | `Nothing , attrs -> attrs, ty
177
+ | `Uncurry , attrs ->
178
+ attrs, Ast_attributes. bs +> ty
179
+ | `Method , _
180
+ -> Location. raise_errorf ~loc " bs.get/set conflicts with bs.meth"
181
+ | `Meth_callback , attrs ->
182
+ attrs, Ast_attributes. bs_this +> ty
183
+ in
184
+ name, attrs, Ast_util. to_method_type loc self " " core_type
185
+ (Ast_literal. type_unit ~loc () ) in
186
+ let no ty =
187
+ let attrs, core_type =
188
+ match Ast_attributes. process_attributes_rev ptyp_attrs with
189
+ | `Nothing , attrs -> attrs, ty
190
+ | `Uncurry , attrs ->
191
+ attrs, Ast_attributes. bs +> ty
192
+ | `Method , attrs ->
193
+ attrs, Ast_attributes. bs_method +> ty
194
+ | `Meth_callback , attrs ->
195
+ attrs, Ast_attributes. bs_this +> ty in
196
+ label, attrs, self.typ self core_type in
197
+ process_getter_setter ~no ~get ~set
198
+ loc label ptyp_attrs core_type acc
199
+ ) methods [] in
200
+ let inner_type =
201
+ { ty
202
+ with ptyp_desc = Ptyp_object (new_methods, closed_flag);
203
+ } in
204
+ if ! record_as_js_object then
205
+ Ast_comb. to_js_type loc inner_type
206
+ else inner_type
207
+ | _ -> super.typ self ty
208
+
209
+ let handle_class_type_fields self fields =
210
+ Ext_list. fold_right
211
+ (handle_class_type_field self)
212
+ fields []
213
+
214
+ let handle_core_type self typ record_as_js_object =
215
+ handle_core_type
216
+ ~super: Bs_ast_mapper. default_mapper
217
+ ~self typ record_as_js_object
0 commit comments