Skip to content

Commit 30223d4

Browse files
authored
Merge pull request #4565 from BuckleScript/clean_up
simplify FFI by taking advantage of polyvar as string
2 parents f18185a + 34b0482 commit 30223d4

16 files changed

+455
-435
lines changed

jscomp/common/bs_warnings.ml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,11 @@
2424

2525

2626

27-
type t =
28-
| Unsafe_poly_variant_type
29-
(* for users write code like this:
30-
{[ external f : [`a of int ] -> string = ""]}
31-
Here users forget about `[@bs.string]` or `[@bs.int]`
32-
*)
3327

3428

3529

36-
let to_string t =
37-
match t with
38-
| Unsafe_poly_variant_type
39-
->
40-
"Here a OCaml polymorphic variant type passed into JS, probably you forgot annotations like `[@bs.int]` or `[@bs.string]` "
4130

4231

43-
let prerr_bs_ffi_warning loc x =
44-
Location.prerr_warning loc (Bs_ffi_warning (to_string x))
45-
4632

4733

4834

jscomp/common/bs_warnings.mli

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@
2323
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
2424

2525

26-
type t =
27-
| Unsafe_poly_variant_type
28-
29-
val prerr_bs_ffi_warning : Location.t -> t -> unit
3026

3127

3228
val warn_missing_primitive : Location.t -> string -> unit

jscomp/core/js_of_lam_variant.ml

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,39 +31,57 @@ type arg_expression =
3131
| Splice2 of E.t * E.t
3232

3333
(* we need destruct [undefined] when input is optional *)
34-
let eval (arg : J.expression) (dispatches : (Ast_compatible.hash_label * string) list ) : E.t =
35-
if arg == E.undefined then E.undefined else
36-
match arg.expression_desc with
37-
| Str (_,s) ->
38-
E.str (Ext_list.assoc_by_string dispatches s None)
39-
| _ ->
40-
E.of_block
41-
[(S.string_switch arg
42-
(Ext_list.map dispatches (fun (i,r) ->
43-
{J.switch_case = i ;
44-
switch_body = [S.return_stmt (E.str r)];
45-
should_break = false; (* FIXME: if true, still print break*)
46-
comment = None;
47-
})))]
34+
let eval (arg : J.expression) (dispatches : (Ast_compatible.hash_label * string) list option) : E.t =
35+
match dispatches with
36+
| None -> arg
37+
| Some dispatches ->
38+
if arg == E.undefined then E.undefined
39+
else
40+
match arg.expression_desc with
41+
| Str (_,s) ->
42+
let s =
43+
(Ext_list.assoc_by_string dispatches s None) in
44+
E.str s
45+
| _ ->
46+
E.of_block
47+
[(S.string_switch arg
48+
(Ext_list.map dispatches (fun (i,r) ->
49+
{J.switch_case = i ;
50+
switch_body = [S.return_stmt (E.str r)];
51+
should_break = false; (* FIXME: if true, still print break*)
52+
comment = None;
53+
})))]
4854

4955
(** invariant: optional is not allowed in this case *)
5056
(** arg is a polyvar *)
51-
let eval_as_event (arg : J.expression) (dispatches : (Ast_compatible.hash_label * string) list ) =
57+
let eval_as_event (arg : J.expression) (dispatches : (Ast_compatible.hash_label * string) list option) =
5258
match arg.expression_desc with
5359
| Caml_block([{expression_desc = Str(_,s)}; cb], _, _, Blk_poly_var ) when Js_analyzer.no_side_effect_expression cb
5460
->
55-
let v = Ext_list.assoc_by_string dispatches s None in
61+
let v =
62+
match dispatches with
63+
| Some dispatches ->
64+
Ext_list.assoc_by_string dispatches s None
65+
| None -> s in
5666
Splice2(E.str v , cb )
5767
| _ ->
5868
Splice2
59-
(E.of_block
60-
[(S.string_switch (E.poly_var_tag_access arg)
61-
(Ext_list.map dispatches (fun (i,r) ->
69+
(
70+
(match dispatches with
71+
| Some dispatches ->
72+
E.of_block
73+
[
74+
75+
(S.string_switch (E.poly_var_tag_access arg)
76+
(Ext_list.map dispatches (fun (i,r) ->
6277
{J.switch_case = i ;
6378
switch_body = [S.return_stmt (E.str r)];
6479
should_break = false; (* FIXME: if true, still print break*)
6580
comment = None;
66-
}) ))]
81+
}) ))
82+
83+
]
84+
| None -> E.poly_var_tag_access arg )
6785
, (* TODO: improve, one dispatch later,
6886
the problem is that we can not create bindings
6987
due to the

jscomp/core/js_of_lam_variant.mli

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,18 @@ type arg_expression =
3030
| Splice2 of J.expression * J.expression
3131

3232
val eval :
33-
J.expression -> (Ast_compatible.hash_label * string) list -> J.expression
33+
J.expression ->
34+
(Ast_compatible.hash_label * string) list option
35+
-> J.expression
36+
3437
val eval_as_event :
35-
J.expression -> (Ast_compatible.hash_label * string) list -> arg_expression
38+
J.expression ->
39+
(Ast_compatible.hash_label * string) list option
40+
-> arg_expression
41+
3642
val eval_as_int :
37-
J.expression -> (Ast_compatible.hash_label * int) list -> J.expression
43+
J.expression ->
44+
(Ast_compatible.hash_label * int) list ->
45+
J.expression
46+
3847
val eval_as_unwrap : J.expression -> J.expression

jscomp/core/lam_compile_external_call.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ let ocaml_to_js_eff
118118
[]
119119
else
120120
[arg])
121-
| NullString dispatches ->
121+
| Poly_var {has_payload = false ; descr = dispatches} ->
122122
Splice1 (Js_of_lam_variant.eval arg dispatches),[]
123-
| NonNullString dispatches ->
123+
| Poly_var {has_payload = true ; descr = dispatches} ->
124124
Js_of_lam_variant.eval_as_event arg dispatches,[]
125125
(* FIXME: encode invariant below in the signature*)
126126
(* length of 2

jscomp/main/builtin_cmi_datasets.ml

Lines changed: 14 additions & 14 deletions
Large diffs are not rendered by default.

jscomp/syntax/ast_external_process.ml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,6 @@ let spec_of_ptyp
9090
begin match ptyp_desc with
9191
| Ptyp_constr ({txt = Lident "unit"; _}, [])
9292
-> if nolabel then Extern_unit else Nothing
93-
| Ptyp_variant _ ->
94-
Bs_warnings.prerr_bs_ffi_warning ptyp.ptyp_loc Unsafe_poly_variant_type;
95-
Nothing
9693
| _ ->
9794
Nothing
9895
end
@@ -440,7 +437,7 @@ let process_obj
440437
{obj_arg_label = External_arg_spec.obj_label s; obj_arg_type},
441438
{param_type with ty = new_ty}::arg_types,
442439
(({Asttypes.txt = name; loc}, [], Ast_literal.type_int ~loc ()) :: result_types)
443-
| NullString _ ->
440+
| Poly_var { has_payload = false ; _} ->
444441
let s = Lam_methname.translate name in
445442
{obj_arg_label = External_arg_spec.obj_label s; obj_arg_type},
446443
{param_type with ty = new_ty }::arg_types,
@@ -449,7 +446,7 @@ let process_obj
449446
Location.raise_errorf ~loc
450447
"The combination of [@@bs.obj], [@@bs.uncurry] is not supported yet"
451448
| Extern_unit -> assert false
452-
| NonNullString _
449+
| Poly_var { has_payload = true ; _}
453450
->
454451
Location.raise_errorf ~loc
455452
"bs.obj label %s does not support such arg type" name
@@ -473,7 +470,7 @@ let process_obj
473470
{obj_arg_label = External_arg_spec.optional s ; obj_arg_type },
474471
param_type :: arg_types,
475472
(({Asttypes.txt = name; loc}, [], Ast_comb.to_undefined_type loc @@ Ast_literal.type_int ~loc ()) :: result_types)
476-
| NullString _ ->
473+
| Poly_var {has_payload = false ; _} ->
477474
let s = Lam_methname.translate name in
478475
{obj_arg_label = External_arg_spec.optional s ; obj_arg_type },
479476
param_type::arg_types,
@@ -485,7 +482,7 @@ let process_obj
485482
Location.raise_errorf ~loc
486483
"The combination of [@@bs.obj], [@@bs.uncurry] is not supported yet"
487484
| Extern_unit -> assert false
488-
| NonNullString _
485+
| Poly_var {has_payload = true; _}
489486
->
490487
Location.raise_errorf ~loc
491488
"bs.obj label %s does not support such arg type" name
@@ -899,7 +896,7 @@ let handle_attributes
899896
| Optional s ->
900897
let arg_type = get_opt_arg_type ~nolabel:false ty in
901898
begin match arg_type with
902-
| NonNullString _ ->
899+
| Poly_var {has_payload = true; _} ->
903900
(* ?x:([`x of int ] [@bs.string]) does not make sense *)
904901
Location.raise_errorf
905902
~loc

jscomp/syntax/ast_polyvar.ml

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,35 +84,36 @@ let map_constructor_declarations_into_ints
8484
*)
8585
let map_row_fields_into_strings ptyp_loc
8686
(row_fields : Parsetree.row_field list) : External_arg_spec.attr =
87+
let has_bs_as = ref false in
8788
let case, result =
8889
Ext_list.fold_right row_fields (`Nothing, []) (fun tag (nullary, acc) ->
8990
match nullary, tag with
9091
| (`Nothing | `Null),
9192
Rtag (label, attrs, true, [])
9293
->
93-
begin match Ast_attributes.iter_process_bs_string_as attrs with
94+
let name =
95+
match Ast_attributes.iter_process_bs_string_as attrs with
9496
| Some name ->
95-
`Null, ((Ast_compatible.hash_label label, name) :: acc )
96-
97-
| None ->
98-
`Null, ((Ast_compatible.hash_label label, Ast_compatible.label_of_name label) :: acc )
99-
end
97+
has_bs_as := true; name
98+
| None -> label.txt
99+
in `Null, (label.txt, name) :: acc
100100
| (`Nothing | `NonNull), Rtag(label, attrs, false, ([ _ ]))
101101
->
102-
begin match Ast_attributes.iter_process_bs_string_as attrs with
102+
let name =
103+
match Ast_attributes.iter_process_bs_string_as attrs with
103104
| Some name ->
104-
`NonNull, ((Ast_compatible.hash_label label, name) :: acc)
105-
| None ->
106-
`NonNull, ((Ast_compatible.hash_label label, Ast_compatible.label_of_name label) :: acc)
107-
end
105+
has_bs_as := true; name
106+
| None -> label.txt
107+
in `NonNull, (label.txt, name) :: acc
108108
| _ -> Bs_syntaxerr.err ptyp_loc Invalid_bs_string_type
109109

110110
) in
111111
match case with
112112
| `Nothing -> Bs_syntaxerr.err ptyp_loc Invalid_bs_string_type
113-
| `Null -> External_arg_spec.NullString result
114-
| `NonNull -> NonNullString result
115-
113+
| `Null
114+
| `NonNull ->
115+
External_arg_spec.Poly_var {has_payload = case = `NonNull ;
116+
descr = if !has_bs_as then Some result else None }
116117

117118
let is_enum row_fields =
118119
List.for_all (fun (x : Parsetree.row_field) ->

jscomp/syntax/external_arg_spec.ml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,16 @@ type label =
4545
| Obj_optional of {name : string }
4646
(* it will be ignored , side effect will be recorded *)
4747

48+
49+
4850
type attr =
49-
| NullString of (Ast_compatible.hash_label * string) list (* `a does not have any value*)
50-
| NonNullString of (Ast_compatible.hash_label * string) list (* `a of int *)
51+
| Poly_var of {
52+
has_payload : bool ;
53+
descr :
54+
(Ast_compatible.hash_label * string) list
55+
option
56+
}
57+
(* `a does not have any value*)
5158
| Int of (Ast_compatible.hash_label * int ) list (* ([`a | `b ] [@bs.int])*)
5259
| Arg_cst of cst
5360
| Fn_uncurry_arity of int (* annotated with [@bs.uncurry ] or [@bs.uncurry 2]*)

jscomp/syntax/external_arg_spec.mli

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,20 @@ type cst = private
3333

3434
type label = private
3535
| Obj_label of {name : string}
36-
(* | Obj_labelCst of {name : string ; cst : cst} *)
3736
| Obj_empty
3837

3938
| Obj_optional of {name : string}
4039
(* it will be ignored , side effect will be recorded *)
4140

41+
42+
4243
type attr =
43-
| NullString of (Ast_compatible.hash_label * string) list (* `a does not have any value*)
44-
| NonNullString of (Ast_compatible.hash_label * string) list (* `a of int *)
44+
| Poly_var of {
45+
has_payload : bool ;
46+
descr :
47+
(Ast_compatible.hash_label * string)
48+
list option
49+
}
4550
| Int of (Ast_compatible.hash_label * int ) list (* ([`a | `b ] [@bs.int])*)
4651
| Arg_cst of cst
4752
| Fn_uncurry_arity of int (* annotated with [@bs.uncurry ] or [@bs.uncurry 2]*)

0 commit comments

Comments
 (0)