@@ -66,7 +66,9 @@ let predef_val_unit =
66
66
let prim = " js_pure_expr"
67
67
let prim_stmt = " js_pure_stmt"
68
68
let prim_debugger = " js_debugger"
69
-
69
+ let curry_type_id = Longident. Ldot (Lident " Js" , " fn" )
70
+ let ignore_id = Longident. Ldot (Lident " Pervasives" , " ignore" )
71
+ let js_unsafe_downgrade_id = Longident. Ldot (Ldot (Lident " Js" , " Unsafe" ), " !" )
70
72
(* note we first declare its type is [unit],
71
73
then [ignore] it, [ignore] is necessary since
72
74
the js value maybe not be of type [unit] and
@@ -77,7 +79,7 @@ let discard_js_value loc e : Parsetree.expression =
77
79
{pexp_desc =
78
80
Pexp_apply
79
81
({pexp_desc =
80
- Pexp_ident {txt = Ldot ( Lident " Pervasives " , " ignore " ) ; loc};
82
+ Pexp_ident {txt = ignore_id ; loc};
81
83
pexp_attributes = [] ;
82
84
pexp_loc = loc},
83
85
[(" " ,
@@ -95,6 +97,135 @@ let discard_js_value loc e : Parsetree.expression =
95
97
}
96
98
97
99
100
+ let gen_fn_run loc arity args : Parsetree.expression_desc =
101
+ let open Parsetree in
102
+ let ptyp_attributes = [] in
103
+ let local_module_name = " Tmp" in
104
+ let local_fun_name = " run" in
105
+ let pval_prim = Printf. sprintf " js_fn_run_%02d" arity in
106
+ let tyvars =
107
+ (Ext_list. init (arity + 1 ) (fun i ->
108
+ {ptyp_desc = Ptyp_var (" a" ^ string_of_int i);
109
+ ptyp_attributes ;
110
+ ptyp_loc = loc})) in
111
+ let tuple_type_desc =
112
+ if arity = 0 then
113
+ (List. hd tyvars).ptyp_desc
114
+ (* avoid single tuple *)
115
+ else
116
+ Parsetree. Ptyp_tuple tyvars
117
+ in
118
+ let uncurry_fn =
119
+ {ptyp_desc =
120
+ Ptyp_constr ({txt = curry_type_id; loc},
121
+ [{ptyp_desc = tuple_type_desc ;
122
+ ptyp_attributes;
123
+ ptyp_loc = loc }]);
124
+ ptyp_attributes;
125
+ ptyp_loc = loc} in
126
+ let arrow a b =
127
+ {ptyp_desc =
128
+ Ptyp_arrow (" " , a, b);
129
+ ptyp_attributes ;
130
+ ptyp_loc = loc} in
131
+ (* * could be optimized *)
132
+ let pval_type =
133
+ Ext_list. reduce_from_right arrow (uncurry_fn :: tyvars) in
134
+ Pexp_letmodule
135
+ ({txt = local_module_name; loc},
136
+ {pmod_desc =
137
+ Pmod_structure
138
+ [{pstr_desc =
139
+ Pstr_primitive
140
+ {pval_name = {txt = local_fun_name; loc};
141
+ pval_type ;
142
+ pval_loc = loc;
143
+ pval_prim = [pval_prim];
144
+ pval_attributes = [] };
145
+ pstr_loc = loc;
146
+ }];
147
+ pmod_loc = loc;
148
+ pmod_attributes = [] },
149
+ {
150
+ pexp_desc =
151
+ Pexp_apply
152
+ (({pexp_desc = Pexp_ident {txt = Ldot (Lident local_module_name, local_fun_name);
153
+ loc};
154
+ pexp_attributes = [] ;
155
+ pexp_loc = loc} : Parsetree. expression),
156
+ args);
157
+ pexp_attributes = [] ;
158
+ pexp_loc = loc
159
+ })
160
+
161
+ let gen_fn_mk loc arity args : Parsetree.expression_desc =
162
+ let open Parsetree in
163
+ let ptyp_attributes = [] in
164
+ let local_module_name = " Tmp" in
165
+ let local_fun_name = " mk" in
166
+ let pval_prim = Printf. sprintf " js_fn_mk_%02d" arity in
167
+ let tyvars =
168
+ (Ext_list. init (arity + 1 ) (fun i ->
169
+ {ptyp_desc = Ptyp_var (" a" ^ string_of_int i);
170
+ ptyp_attributes ;
171
+ ptyp_loc = loc})) in
172
+ let tuple_type_desc =
173
+ if arity = 0 then
174
+ (List. hd tyvars).ptyp_desc
175
+ (* avoid single tuple *)
176
+ else
177
+ Parsetree. Ptyp_tuple tyvars
178
+ in
179
+ let uncurry_fn =
180
+ {ptyp_desc =
181
+ Ptyp_constr ({txt = curry_type_id; loc},
182
+ [{ptyp_desc = tuple_type_desc ;
183
+ ptyp_attributes;
184
+ ptyp_loc = loc }]);
185
+ ptyp_attributes;
186
+ ptyp_loc = loc} in
187
+ let arrow a b =
188
+ {ptyp_desc =
189
+ Ptyp_arrow (" " , a, b);
190
+ ptyp_attributes ;
191
+ ptyp_loc = loc} in
192
+ (* * could be optimized *)
193
+ let pval_type =
194
+ if arity = 0 then
195
+ arrow (arrow predef_unit_type (List. hd tyvars) ) uncurry_fn
196
+ else
197
+ arrow (Ext_list. reduce_from_right arrow tyvars) uncurry_fn in
198
+
199
+ Pexp_letmodule
200
+ ({txt = local_module_name; loc},
201
+ {pmod_desc =
202
+ Pmod_structure
203
+ [{pstr_desc =
204
+ Pstr_primitive
205
+ {pval_name = {txt = local_fun_name; loc};
206
+ pval_type ;
207
+ pval_loc = loc;
208
+ pval_prim = [pval_prim];
209
+ pval_attributes = [] };
210
+ pstr_loc = loc;
211
+ }];
212
+ pmod_loc = loc;
213
+ pmod_attributes = [] },
214
+ {
215
+ pexp_desc =
216
+ Pexp_apply
217
+ (({pexp_desc = Pexp_ident {txt = Ldot (Lident local_module_name, local_fun_name);
218
+ loc};
219
+ pexp_attributes = [] ;
220
+ pexp_loc = loc} : Parsetree. expression),
221
+ args);
222
+ pexp_attributes = [] ;
223
+ pexp_loc = loc
224
+ })
225
+
226
+
227
+
228
+
98
229
let handle_raw ?ty loc e attrs =
99
230
let attrs =
100
231
match ty with
@@ -151,7 +282,7 @@ let uncurry_fn_type loc ty ptyp_attributes
151
282
ptyp_attributes }
152
283
in
153
284
{ ty with ptyp_desc =
154
- Ptyp_constr ({txt = Ldot ( Lident " Fn " , " t " ) ; loc},
285
+ Ptyp_constr ({txt = curry_type_id ; loc},
155
286
[ fn_type]);
156
287
ptyp_attributes = []
157
288
}
@@ -246,44 +377,26 @@ let handle_uncurry_generation loc
246
377
| v -> [v]
247
378
in
248
379
let len = List. length args in
249
- let mk = " mk" ^ string_of_int len in
250
380
let body = mapper.expr mapper body in
251
- begin match args with
252
- | [] ->
253
- {e with pexp_desc =
254
- Pexp_apply (
255
- {pexp_desc = Pexp_ident {txt = Ldot (Lident " Fn" , mk); loc};
256
- pexp_loc = loc;
257
- pexp_attributes = []
258
- },
259
- [(" " ,
260
- {pexp_desc =
261
- Pexp_fun (" " , None ,
262
- {ppat_desc =
263
- Ppat_construct ({txt = Lident " ()" ; loc}, None );
264
- ppat_loc = loc ;
265
- ppat_attributes = [] },
266
- body);
267
- pexp_loc = loc ;
268
- pexp_attributes = [] })])}
269
- | _ ->
270
- let fun_ =
271
- List. fold_right (fun arg body ->
272
- let arg = mapper.pat mapper arg in
273
- {Parsetree.
274
- pexp_loc = loc ;
275
- pexp_desc = Pexp_fun (" " , None , arg, body);
276
- pexp_attributes = [] }) args body in
277
- { e with
278
- pexp_desc =
279
- Pexp_apply ({pexp_desc = Pexp_ident {txt = Ldot (Lident " Fn" , mk); loc};
280
- pexp_loc = loc ;
281
- pexp_attributes = [] },
282
- [(" " ,
283
- fun_)])
284
- }
285
- end
286
-
381
+ let fun_ =
382
+ if len = 0 then
383
+ {Parsetree. pexp_desc =
384
+ Pexp_fun (" " , None ,
385
+ {ppat_desc =
386
+ Ppat_construct ({txt = Lident " ()" ; loc}, None );
387
+ ppat_loc = loc ;
388
+ ppat_attributes = [] },
389
+ body);
390
+ pexp_loc = loc ;
391
+ pexp_attributes = [] }
392
+ else
393
+ List. fold_right (fun arg body ->
394
+ let arg = mapper.pat mapper arg in
395
+ {Parsetree.
396
+ pexp_loc = loc ;
397
+ pexp_desc = Pexp_fun (" " , None , arg, body);
398
+ pexp_attributes = [] }) args body in
399
+ {e with pexp_desc = gen_fn_mk loc len [(" " , fun_)]}
287
400
let handle_uncurry_application
288
401
loc fn (pat : Parsetree.expression ) (e : Parsetree.expression )
289
402
(self : Ast_mapper.mapper )
@@ -302,18 +415,7 @@ let handle_uncurry_application
302
415
let fn = self.expr self fn in
303
416
let args = List. map (self.expr self) args in
304
417
let len = List. length args in
305
- let run = " run" ^ string_of_int len in
306
- { e with
307
- Parsetree. pexp_desc =
308
- Pexp_apply (
309
- {pexp_desc =
310
- Pexp_ident {txt = Ldot (Lident " Fn" , run) ;
311
- loc ; };
312
- pexp_loc = loc ;
313
- pexp_attributes = []
314
- },
315
- ((" " , fn) :: List. map (fun x -> " " , x) args))
316
- }
418
+ { e with pexp_desc = gen_fn_run loc len ((" " , fn) :: List. map (fun x -> " " , x) args)}
317
419
318
420
let handle_obj_property loc obj name e
319
421
(mapper : Ast_mapper.mapper ) : Parsetree.expression =
@@ -324,7 +426,7 @@ let handle_obj_property loc obj name e
324
426
({pexp_desc =
325
427
Pexp_apply
326
428
({pexp_desc =
327
- Pexp_ident {txt = Ldot ( Ldot ( Lident " Js " , " Unsafe " ), " ! " ) ;
429
+ Pexp_ident {txt = js_unsafe_downgrade_id ;
328
430
loc};
329
431
pexp_loc = loc;
330
432
pexp_attributes = [] },
@@ -370,39 +472,27 @@ let handle_obj_method loc (obj : Parsetree.expression)
370
472
let len = List. length args in
371
473
let obj = mapper.expr mapper obj in
372
474
let args = List. map (mapper.expr mapper ) args in
373
- (* TODO: in the future, dynamically create the c externs,
374
- so it can handle arbitrary large number
375
- *)
376
- let run = " run" ^ string_of_int len in
377
- { e with
378
- pexp_desc =
379
- Pexp_apply (
380
- {pexp_desc =
381
- Pexp_ident {txt = Ldot (Lident " Fn" , run) ;
382
- loc ; };
383
- pexp_loc = loc ;
384
- pexp_attributes = []
385
- },
386
- ((" " ,
387
- {pexp_desc =
388
- Pexp_send
389
- ({pexp_desc =
390
- Pexp_apply
391
- ({pexp_desc =
392
- Pexp_ident {
393
- txt = Ldot (Ldot (Lident " Js" , " Unsafe" ), " !" );
394
- loc };
395
- pexp_loc = loc ;
396
- pexp_attributes = [] },
397
- [(" " , obj)]);
398
- pexp_loc = loc ;
399
- pexp_attributes = [] },
400
- name);
401
- pexp_loc = loc ;
402
- pexp_attributes = [] }) ::
403
- List. map (fun x -> " " , x) args
404
- ))
405
- }
475
+
476
+ {e with pexp_desc = gen_fn_run loc len
477
+ ((" " ,
478
+ {pexp_desc =
479
+ Pexp_send
480
+ ({pexp_desc =
481
+ Pexp_apply
482
+ ({pexp_desc =
483
+ Pexp_ident {
484
+ txt = js_unsafe_downgrade_id;
485
+ loc };
486
+ pexp_loc = loc ;
487
+ pexp_attributes = [] },
488
+ [(" " , obj)]);
489
+ pexp_loc = loc ;
490
+ pexp_attributes = [] },
491
+ name);
492
+ pexp_loc = loc ;
493
+ pexp_attributes = [] }) ::
494
+ List. map (fun x -> " " , x) args
495
+ )}
406
496
(* * TODO:
407
497
More syntax sanity check for [case__set]
408
498
case__set: arity 2
0 commit comments