11(* For implicit optional argument elimination. Annoying with Ast_helper. *)
22[@@@ ocaml.warning " -48" ]
3-
43open Ast_mapper
54open Ast_helper
65open Asttypes
@@ -52,8 +51,7 @@ let random_tvar () =
5251
5352let inside_Js = lazy
5453 (try
55- Filename. basename @@
56- Filename. chop_extension ! Location. input_name = " js"
54+ Filename. basename @@ Filename. chop_extension ! Location. input_name = " js"
5755 with Invalid_argument _ -> false )
5856
5957module Js = struct
@@ -114,7 +112,7 @@ let constrain_types ?loc obj res res_typ meth meth_typ args =
114112 (* [($obj$ : <typ_var> Js.t)] *)
115113 let cstr =
116114 Exp. constraint_
117- [% expr ([% e obj] : < .. > Js.t ) ]
115+ [% expr ([% e obj] : [%t Js.type_ "t" [ [%type: < .. > ] ] ] ) ]
118116 (Js. type_ " t" [typ_var] )
119117 in
120118
@@ -169,15 +167,19 @@ let method_call ~loc obj meth args =
169167
170168 let type_binders = List. map (fun (_ ,ev ,_ ,(_ ,t )) -> (ev,t)) args in
171169
172- Exp. let_
173- Nonrecursive
174- ( List. map ( fun ( e , _ , pv , _ ) -> Vb. mk pv e) args)
170+ let bindings = List. map ( fun ( e , _ , pv , _ ) -> Vb. mk pv e) args in
171+
172+ let body =
175173 [% expr
176174 let [% p p_obj] = [% e obj] in
177175 let [% p p_res] = [% e meth_call]
178176 in
179177 [% e constrain_types ~loc e_obj e_res ret_type meth method_type type_binders]
180178 ]
179+ in
180+ match bindings with
181+ | [] -> body
182+ | _ -> Exp. let_ Nonrecursive bindings body
181183
182184(* * Instantiation of a class, used by new%js. *)
183185let new_object constr args =
@@ -216,7 +218,8 @@ let format_meth body =
216218 - No duplicated declaration
217219 - Only relevant declarations (val and method, for now).
218220*)
219- let preprocess_literal_object fields =
221+
222+ let preprocess_literal_object mappper fields =
220223
221224 let check_name id names =
222225 if S. mem id.txt names then
@@ -230,11 +233,21 @@ let preprocess_literal_object fields =
230233
231234 let f (names , fields ) exp = match exp.pcf_desc with
232235 | Pcf_val (id , mut , Cfk_concrete (bang , body )) ->
236+ let ty = fresh_type id.loc in
233237 let names = check_name id names in
234- names, (`Val (id, mut, bang, body) :: fields)
238+ let body = mappper body in
239+ names, (`Val (id, mut, bang, body, ty) :: fields)
235240 | Pcf_method (id , priv , Cfk_concrete (bang , body )) ->
236241 let names = check_name id names in
237- names, (`Meth (id, priv, bang, format_meth body) :: fields)
242+ let body = format_meth (mappper body) in
243+ let rec create_meth_ty exp = match exp.pexp_desc with
244+ | Pexp_fun (label ,_ ,_ ,body ) ->
245+ (label, fresh_type exp.pexp_loc) :: create_meth_ty body
246+ | _ -> []
247+ in
248+ let ret_ty = fresh_type body.pexp_loc in
249+ let fun_ty = create_meth_ty body in
250+ names, (`Meth (id, priv, bang, body, (fun_ty, ret_ty)) :: fields)
238251 | _ ->
239252 Location. raise_errorf ~loc: exp.pcf_loc
240253 " This field is not valid inside a js literal object."
271284let literal_object self_id fields =
272285 let self_type = random_tvar () in
273286
274- let fields =
275- List. map (function
276- | `Val (n , mut , bang , body ) ->
277- let ty = fresh_type n.loc in
278- `Val (n, mut, bang, body, ty)
279- | `Meth (n , priv , bang , body ) ->
280- let rec create_meth_ty exp = match exp.pexp_desc with
281- | Pexp_fun (label ,_ ,_ ,body ) ->
282- (label, fresh_type exp.pexp_loc) :: create_meth_ty body
283- | _ -> []
284- in
285- let ret_ty = fresh_type body.pexp_loc in
286- let fun_ty = create_meth_ty body in
287- let self_and_body = [% expr fun [%p self_id ] -> [% e body]] in
288- `Meth (n, priv, bang, self_and_body, (fun_ty, ret_ty))
289- )
290- fields
291- in
292-
293287 let create_method_type = function
294288 | `Val (id , Mutable, _ , _body , ty ) ->
295289 (id.txt, [] , Js. type_ " prop" [ty])
@@ -329,7 +323,7 @@ let literal_object self_id fields =
329323 Js. fun_
330324 " wrap_meth_callback"
331325 [
332- annotate_body ((Js. nolabel,Typ. var self_type) :: fun_ty) ret_ty body
326+ annotate_body ((Js. nolabel,Typ. var self_type) :: fun_ty) ret_ty [ % expr fun [% p self_id ] -> [ % e body]]
333327 ])
334328
335329 in
@@ -365,96 +359,99 @@ let literal_object self_id fields =
365359let js_mapper _args =
366360 { default_mapper with
367361 expr = (fun mapper expr ->
362+ let prev_default_loc = ! default_loc in
368363 default_loc := expr.pexp_loc;
369364 let { pexp_attributes; _ } = expr in
370- match expr with
371-
372- (* obj##.var *)
373- | [% expr [% e? obj] ##. [% e? meth] ] ->
374- let meth = exp_to_string meth in
375- let e_obj, p_obj = mk_id ~loc: obj.pexp_loc " jsoo_obj" in
376- let e_res, p_res = mk_id ~loc: expr.pexp_loc " jsoo_res" in
377- let new_expr =
378- [% expr
379- let [% p p_obj] = [% e obj] in
380- let [% p p_res] = [% e Js. unsafe " get" [e_obj ; str @@ unescape meth]] in
381- [% e
382- constrain_types
383- e_obj
384- e_res [% type : 'jsoo_res]
385- meth (Js. type_ " gen_prop" [[% type : < get : 'jsoo_res; ..> ]])
386- []
365+ let new_expr = match expr with
366+ (* obj##.var *)
367+ | [% expr [% e? obj] ##. [% e? meth] ] ->
368+ let obj = mapper.expr mapper obj in
369+ let meth = exp_to_string meth in
370+ let e_obj, p_obj = mk_id ~loc: obj.pexp_loc " jsoo_obj" in
371+ let e_res, p_res = mk_id ~loc: expr.pexp_loc " jsoo_res" in
372+ let new_expr =
373+ [% expr
374+ let [% p p_obj] = [% e obj] in
375+ let [% p p_res] = [% e Js. unsafe " get" [e_obj ; str @@ unescape meth]] in
376+ [% e
377+ constrain_types
378+ e_obj
379+ e_res [% type : 'jsoo_res]
380+ meth (Js. type_ " gen_prop" [[% type : < get : 'jsoo_res; ..> ]])
381+ []
382+ ]
387383 ]
388- ]
389- in mapper.expr mapper { new_expr with pexp_attributes }
390-
391- (* obj##.var := value *)
392- | [% expr [% e? [% expr [% e? obj] ##. [% e? meth]] as res] := [% e? value]] ->
393- default_loc := res.pexp_loc ;
394- let meth = exp_to_string meth in
395- let e_obj, p_obj = mk_id ~loc: obj.pexp_loc " jsoo_obj" in
396- let e_value, p_value = mk_id ~loc: value.pexp_loc " jsoo_arg" in
397- let new_expr =
398- [% expr
399- let [% p p_obj] = [% e obj]
400- and [% p p_value] = [% e value] in
401- let _ = [% e
402- constrain_types
403- e_obj
404- e_value [% type : 'jsoo_arg]
405- meth (Js. type_ " gen_prop" [[% type : < set : 'jsoo_arg -> unit ; ..> ]])
406- []
384+ in
385+ mapper.expr mapper { new_expr with pexp_attributes }
386+
387+ (* obj##.var := value *)
388+ | [% expr [% e? [% expr [% e? obj] ##. [% e? meth]] as res] := [% e? value]] ->
389+ default_loc := res.pexp_loc ;
390+ let obj = mapper.expr mapper obj in
391+ let value = mapper.expr mapper value in
392+ let meth = exp_to_string meth in
393+ let e_obj, p_obj = mk_id ~loc: obj.pexp_loc " jsoo_obj" in
394+ let e_value, p_value = mk_id ~loc: value.pexp_loc " jsoo_arg" in
395+ let new_expr =
396+ [% expr
397+ let [% p p_obj] = [% e obj]
398+ and [% p p_value] = [% e value] in
399+ let _ = [% e
400+ constrain_types
401+ e_obj
402+ e_value [% type : 'jsoo_arg]
403+ meth (Js. type_ " gen_prop" [[% type : < set : 'jsoo_arg -> unit ; ..> ]])
404+ []
405+ ]
406+ in
407+ [% e Js. unsafe ~loc: expr.pexp_loc " set" [ e_obj ; str @@ unescape meth ; e_value]]
407408 ]
408- in
409- [% e Js. unsafe ~loc: expr.pexp_loc " set" [ e_obj ; str @@ unescape meth ; e_value]]
410- ]
411- in mapper.expr mapper { new_expr with pexp_attributes }
412-
413- (* obj##meth arg1 arg2 .. *)
414- (* obj##(meth arg1 arg2) .. *)
415- | {pexp_desc = Pexp_apply
416- (([% expr [% e? obj] ## [% e? meth]] as expr), args);
417- _
418- }
419- | [% expr [% e? obj] ## [% e? {pexp_desc = Pexp_apply ((meth as expr),args); _ }]]
420- ->
421- let meth = exp_to_string meth in
422- let new_expr =
423- method_call ~loc: expr.pexp_loc obj meth args
424- in mapper.expr mapper { new_expr with pexp_attributes }
425- (* obj##meth *)
426- | ([%expr [%e ? obj ] ## [%e ? meth ]] as expr ) ->
427- let meth = exp_to_string meth in
428- let new_expr =
429- method_call ~loc: expr.pexp_loc obj meth []
430- in mapper.expr mapper { new_expr with pexp_attributes }
431-
432-
433- (* new%js constr] *)
434- | [% expr [% js [% e? {pexp_desc = Pexp_new constr; _}]]] ->
435- let new_expr =
436- new_object constr []
437- in mapper.expr mapper { new_expr with pexp_attributes }
438- (* new%js constr arg1 arg2 ..)] *)
439- | {pexp_desc = Pexp_apply
440- ([% expr [% js [% e? {pexp_desc = Pexp_new constr; _}]]]
441- , args);
442- _
443- } ->
444- let new_expr =
445- new_object constr args
446- in mapper.expr mapper { new_expr with pexp_attributes }
447-
448-
449- (* object%js ... end *)
450- | [% expr [% js [% e? {pexp_desc = Pexp_object class_struct; _} ]]] ->
451- let fields = preprocess_literal_object class_struct.pcstr_fields in
452- let new_expr = match fields with
453- | `Fields fields ->
454- literal_object class_struct.pcstr_self fields
455- | `Error e -> Exp. extension e
456- in mapper.expr mapper { new_expr with pexp_attributes }
457-
458- | _ -> default_mapper.expr mapper expr
409+ in
410+ mapper.expr mapper { new_expr with pexp_attributes }
411+
412+ (* obj##meth arg1 arg2 .. *)
413+ (* obj##(meth arg1 arg2) .. *)
414+ | {pexp_desc = Pexp_apply (([% expr [% e? obj] ## [% e? meth]] as expr), args); _}
415+ | [% expr [% e? obj] ## [% e? {pexp_desc = Pexp_apply ((meth as expr),args); _}]]
416+ ->
417+ let meth = exp_to_string meth in
418+ let obj = mapper.expr mapper obj in
419+ let args = List. map (fun (s ,e ) -> s, mapper.expr mapper e) args in
420+ let new_expr = method_call ~loc: expr.pexp_loc obj meth args in
421+ mapper.expr mapper { new_expr with pexp_attributes }
422+ (* obj##meth *)
423+ | ([%expr [%e ? obj ] ## [%e ? meth ]] as expr ) ->
424+ let obj = mapper.expr mapper obj in
425+ let meth = exp_to_string meth in
426+ let new_expr = method_call ~loc: expr.pexp_loc obj meth [] in
427+ mapper.expr mapper { new_expr with pexp_attributes }
428+
429+ (* new%js constr] *)
430+ | [% expr [% js [% e? {pexp_desc = Pexp_new constr; _}]]] ->
431+ let new_expr = new_object constr [] in
432+ mapper.expr mapper { new_expr with pexp_attributes }
433+ (* new%js constr arg1 arg2 ..)] *)
434+ | {pexp_desc = Pexp_apply
435+ ([% expr [% js [% e? {pexp_desc = Pexp_new constr; _}]]]
436+ , args); _ } ->
437+ let args = List. map (fun (s ,e ) -> s, mapper.expr mapper e) args in
438+ let new_expr =
439+ new_object constr args
440+ in
441+ mapper.expr mapper { new_expr with pexp_attributes }
442+
443+ (* object%js ... end *)
444+ | [% expr [% js [% e? {pexp_desc = Pexp_object class_struct; _} ]]] ->
445+ let fields = preprocess_literal_object (mapper.expr mapper) class_struct.pcstr_fields in
446+ let new_expr = match fields with
447+ | `Fields fields ->
448+ literal_object class_struct.pcstr_self fields
449+ | `Error e -> Exp. extension e in
450+ mapper.expr mapper { new_expr with pexp_attributes }
451+
452+ | _ -> default_mapper.expr mapper expr
453+ in
454+ default_loc := prev_default_loc;
455+ new_expr
459456 )
460457 }
0 commit comments