@@ -76,6 +76,12 @@ let arrow = Ast_helper.Typ.arrow
76
76
77
77
let record_as_js_object = ref None (* otherwise has an attribute *)
78
78
let obj_type_as_js_obj_type = ref false
79
+ let uncurry_type = ref false
80
+ let obj_type_auto_uncurry = ref false
81
+ let non_export = ref false
82
+ let lift_js_type ~loc x = Typ. constr ~loc {txt = js_obj_type_id () ; loc} [x]
83
+ let lift_curry_type ~loc x = Typ. constr ~loc {txt = curry_type_id () ; loc} [x]
84
+
79
85
let handle_record_as_js_object
80
86
loc
81
87
attr
@@ -96,10 +102,9 @@ let handle_record_as_js_object
96
102
Typ. var ~loc (" a" ^ string_of_int i))) in
97
103
98
104
let result_type =
99
- Typ. constr ~loc {txt = js_obj_type_id () ; loc}
100
- [
101
- Typ. object_ ~loc (List. map2 (fun x y -> x ,[] , y) labels tyvars) Closed
102
- ]
105
+ lift_js_type ~loc
106
+ @@ Typ. object_ ~loc (List. map2 (fun x y -> x ,[] , y) labels tyvars) Closed
107
+
103
108
in
104
109
List. fold_right2
105
110
(fun label tyvar acc -> arrow ~loc label tyvar acc) labels tyvars result_type
@@ -126,8 +131,7 @@ let gen_fn_run loc arity args : Parsetree.expression_desc =
126
131
Parsetree. Ptyp_tuple tyvars
127
132
in
128
133
let uncurry_fn =
129
- Typ. constr ~loc {txt = curry_type_id () ; loc}
130
- [ Typ. mk ~loc tuple_type_desc] in
134
+ lift_curry_type ~loc @@ Typ. mk ~loc tuple_type_desc in
131
135
(* * could be optimized *)
132
136
let pval_type =
133
137
Ext_list. reduce_from_right (fun a b -> arrow ~loc " " a b) (uncurry_fn :: tyvars) in
@@ -153,8 +157,7 @@ let gen_fn_mk loc arity args : Parsetree.expression_desc =
153
157
Parsetree. Ptyp_tuple tyvars
154
158
in
155
159
let uncurry_fn =
156
- Typ. constr ~loc {txt = curry_type_id () ; loc}
157
- [Typ. mk ~loc tuple_type_desc]
160
+ lift_curry_type ~loc @@ Typ. mk ~loc tuple_type_desc
158
161
in
159
162
let arrow = arrow ~loc " " in
160
163
(* * could be optimized *)
@@ -163,10 +166,8 @@ let gen_fn_mk loc arity args : Parsetree.expression_desc =
163
166
arrow (arrow (Ast_literal. type_unit ~loc () ) (List. hd tyvars) ) uncurry_fn
164
167
else
165
168
arrow (Ext_list. reduce_from_right arrow tyvars) uncurry_fn in
166
- let local_module_name = " Tmp" in
167
- let local_fun_name = " mk" in
168
169
Ast_comb. create_local_external loc ~pval_prim ~pval_type
169
- ~local_module_name ~local_fun_name args
170
+ args
170
171
171
172
172
173
let find_uncurry_attrs_and_remove (attrs : Parsetree.attributes ) =
@@ -192,10 +193,10 @@ let uncurry_fn_type loc ty attrs
192
193
| v ->
193
194
Typ. tuple ~loc ~attrs [v ; body]
194
195
in
195
- Typ. constr ~loc {txt = curry_type_id () ; loc} [ fn_type]
196
+ lift_curry_type ~loc fn_type
197
+
196
198
197
199
198
- let uncurry_type = ref false
199
200
200
201
(*
201
202
Attributes are very hard to attribute
@@ -239,27 +240,31 @@ let handle_typ
239
240
| _ -> false )
240
241
ptyp_attributes with
241
242
| None , None , _ ->
243
+ let check_auto_uncurry core_type =
244
+ if ! obj_type_auto_uncurry then
245
+ Ext_ref. protect uncurry_type true (fun _ -> self.typ self core_type )
246
+ else self.typ self core_type in
247
+
242
248
let methods =
243
249
List. map (fun (label , ptyp_attrs , core_type ) ->
244
250
match find_uncurry_attrs_and_remove ptyp_attrs with
245
- | None , _ -> label, ptyp_attrs , self.typ self core_type
251
+ | None , _ ->
252
+ label, ptyp_attrs , check_auto_uncurry core_type
246
253
| Some v , ptyp_attrs ->
247
- label , ptyp_attrs, self.typ self
254
+ label , ptyp_attrs,
255
+ check_auto_uncurry
248
256
{ core_type with ptyp_attributes = v :: core_type .ptyp_attributes}
249
257
) methods
250
258
in
251
259
if ! obj_type_as_js_obj_type then
252
- {ptyp_desc =
253
- Ptyp_constr ({ txt = js_obj_type_id () ; loc},
254
- [{ ty with ptyp_desc = Ptyp_object (methods, closed_flag);
255
- ptyp_attributes }]);
256
- ptyp_attributes = [] ;
257
- ptyp_loc = loc }
260
+ lift_js_type ~loc { ty with ptyp_desc = Ptyp_object (methods, closed_flag);
261
+ ptyp_attributes }
262
+
258
263
else
259
264
{ty with ptyp_desc = Ptyp_object (methods, closed_flag)}
260
265
| fact1 , fact2 , ptyp_attributes ->
261
266
let obj_type_as_js_obj_type_cxt = fact1 <> None || ! obj_type_as_js_obj_type in
262
- let uncurry_type_cxt = fact2 <> None || ! uncurry_type in
267
+ let uncurry_type_cxt = fact2 <> None || ! uncurry_type || ! obj_type_auto_uncurry in
263
268
let methods =
264
269
Ext_ref. protect2
265
270
obj_type_as_js_obj_type
@@ -287,7 +292,7 @@ let handle_typ
287
292
end
288
293
| _ -> super.typ self ty
289
294
290
- let handle_ctyp
295
+ let handle_class_obj_typ
291
296
(super : Ast_mapper.mapper )
292
297
(self : Ast_mapper.mapper )
293
298
(ty : Parsetree.class_type ) =
@@ -301,7 +306,13 @@ let handle_ctyp
301
306
Ext_ref. protect uncurry_type true begin fun () ->
302
307
self.class_type self {ty with pcty_attributes = pcty_attributes'}
303
308
end
304
- | None , _ -> super.class_type self ty
309
+ | None , _ ->
310
+ if ! obj_type_auto_uncurry then
311
+ Ext_ref. protect uncurry_type true begin fun () ->
312
+ super.class_type self ty
313
+ end
314
+ else
315
+ super.class_type self ty
305
316
end
306
317
307
318
@@ -374,13 +385,8 @@ let handle_obj_property loc obj name e
374
385
~pval_prim: " js_unsafe_downgrade"
375
386
~pval_type: (
376
387
Ast_comb. arrow_no_label ~loc
377
- (Typ. constr ~loc
378
- {txt = js_obj_type_id () ; loc}
379
- [var])
380
- var)
381
-
382
- ~local_module_name: " Tmp"
383
- ~local_fun_name: " cast" [" " , obj] in
388
+ (lift_js_type ~loc var) var)
389
+ [" " , obj] in
384
390
{ e with pexp_desc =
385
391
Pexp_send
386
392
({pexp_desc = down ;
@@ -429,20 +435,12 @@ let handle_obj_method loc (obj : Parsetree.expression)
429
435
let down = Ast_comb. create_local_external loc
430
436
~pval_prim: " js_unsafe_downgrade"
431
437
~pval_type: (Ast_comb. arrow_no_label ~loc
432
- (Typ. constr ~loc {txt = js_obj_type_id () ; loc} [ var] )
438
+ (lift_js_type ~loc var)
433
439
var )
434
440
~local_module_name: " Tmp"
435
441
~local_fun_name: " cast" [" " , obj] in
436
442
{e with pexp_desc = gen_fn_run loc len
437
- ((" " ,
438
- {pexp_desc =
439
- Pexp_send
440
- ({pexp_desc = down ;
441
- pexp_loc = loc ;
442
- pexp_attributes = [] },
443
- name);
444
- pexp_loc = loc ;
445
- pexp_attributes = [] }) ::
443
+ ((" " , Exp. send ~loc (Exp. mk ~loc down) name) ::
446
444
List. map (fun x -> " " , x) args
447
445
)}
448
446
(* * TODO:
@@ -610,7 +608,7 @@ let rec unsafe_mapper : Ast_mapper.mapper =
610
608
| _ -> Ast_mapper. default_mapper.expr mapper e
611
609
);
612
610
typ = (fun self typ -> handle_typ Ast_mapper. default_mapper self typ);
613
- class_type = (fun self ctyp -> handle_ctyp Ast_mapper. default_mapper self ctyp);
611
+ class_type = (fun self ctyp -> handle_class_obj_typ Ast_mapper. default_mapper self ctyp);
614
612
structure_item = (fun mapper (str : Parsetree.structure_item ) ->
615
613
begin match str.pstr_desc with
616
614
| Pstr_extension ( ({txt = " bs.raw" ; loc}, payload), _attrs)
@@ -635,11 +633,70 @@ let rec unsafe_mapper : Ast_mapper.mapper =
635
633
end
636
634
)
637
635
}
636
+
637
+
638
+ let common_actions_table :
639
+ (string * (Parsetree. expression -> unit )) list =
640
+ [ " obj_type_auto_uncurry" ,
641
+ (fun e ->
642
+ obj_type_auto_uncurry := Ast_payload. assert_bool_lit e
643
+ )
644
+ ]
645
+
646
+
647
+ let structural_config_table =
648
+ String_map. of_list
649
+ (( " non_export" ,
650
+ (fun e -> non_export := Ast_payload. assert_bool_lit e ))
651
+ :: common_actions_table)
652
+
653
+ let signature_config_table =
654
+ String_map. of_list common_actions_table
655
+
656
+
657
+ let make_call_back table ((x : Longident.t Asttypes.loc ) , y ) =
658
+ match x with
659
+ | {txt = Lident name ; loc } ->
660
+ begin match String_map. find name table with
661
+ | fn -> fn y
662
+ | exception _ -> Location. raise_errorf ~loc " %s is not supported" name
663
+ end
664
+ | {loc} ->
665
+ Location. raise_errorf ~loc " invalid label for config"
666
+
638
667
let rewrite_signature : (Parsetree.signature -> Parsetree.signature) ref =
639
668
ref (fun x ->
640
- unsafe_mapper.signature unsafe_mapper x
669
+ match (x : Parsetree.signature ) with
670
+ | {psig_desc = Psig_attribute ({txt = " bs.config" ; loc}, payload); _} :: rest
671
+ ->
672
+ begin
673
+ Ast_payload. as_record_and_process loc payload
674
+ (make_call_back signature_config_table) ;
675
+ unsafe_mapper.signature unsafe_mapper rest
676
+ end
677
+ | _ ->
678
+ unsafe_mapper.signature unsafe_mapper x
641
679
)
642
680
643
681
let rewrite_implementation : (Parsetree.structure -> Parsetree.structure) ref =
644
- ref (fun x -> unsafe_mapper.structure unsafe_mapper x )
682
+ ref (fun (x : Parsetree.structure ) ->
683
+ match x with
684
+ | {pstr_desc = Pstr_attribute ({txt = " bs.config" ; loc}, payload); _} :: rest
685
+ ->
686
+ begin
687
+ Ast_payload. as_record_and_process loc payload
688
+ (make_call_back structural_config_table) ;
689
+ let rest = unsafe_mapper.structure unsafe_mapper rest in
690
+ if ! non_export then
691
+ [Str. include_ ~loc
692
+ (Incl. mk ~loc
693
+ (Mod. constraint_ ~loc
694
+ (Mod. structure ~loc rest )
695
+ (Mty. signature ~loc [] )
696
+ ))]
697
+ else rest
698
+
699
+ end
700
+ | _ ->
701
+ unsafe_mapper.structure unsafe_mapper x )
645
702
0 commit comments