Skip to content

Commit 25db82b

Browse files
authored
Merge pull request #2783 from BuckleScript/arity_infer
lift function limitation in bs.deriving abstract, fix #2776
2 parents 6ae1b45 + a8560da commit 25db82b

16 files changed

+550
-352
lines changed

jscomp/all.depend

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ syntax/external_process.cmx : common/lam_methname.cmx \
221221
syntax/ast_core_type.cmx syntax/ast_comb.cmx syntax/ast_attributes.cmx \
222222
syntax/external_process.cmi
223223
syntax/ast_derive_abstract.cmx : syntax/external_process.cmx \
224+
syntax/external_ffi_types.cmx syntax/external_arg_spec.cmx \
224225
ext/ext_list.cmx syntax/ast_literal.cmx syntax/ast_derive_util.cmx \
225226
syntax/ast_core_type.cmx syntax/ast_attributes.cmx \
226227
syntax/ast_derive_abstract.cmi

jscomp/bin/all_ounit_tests.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4155,13 +4155,13 @@ external ff :
41554155
OUnit.assert_bool __LOC__
41564156
(Ext_string.contain_substring should_err.stderr "contravariant")
41574157
end;
4158-
__LOC__ >:: begin fun _ ->
4158+
(* __LOC__ >:: begin fun _ ->
41594159
let should_err = bsc_check_eval {|
41604160
type 'a t = {k : int -> 'a } [@@bs.deriving abstract]
41614161
|} in
41624162
OUnit.assert_bool __LOC__
41634163
(Ext_string.contain_substring should_err.stderr "not allowed")
4164-
end
4164+
end *)
41654165
(* __LOC__ >:: begin fun _ -> *)
41664166
(* let should_infer = perform_bsc [| "-i"; "-bs-eval"|] {| *)
41674167
(* let f = fun [@bs] x -> let (a,b) = x in a + b *)

jscomp/bsb/bsb_templates.ml

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -549,15 +549,12 @@ let root = OCamlRes.Res.([
549549
\ \"You've clicked this \" ++ string_of_int(self.state.count) ++ \" times(s)\";\n\
550550
\ <div>\n\
551551
\ <button onClick=(_event => self.send(Click))>\n\
552-
\ (ReasonReact.stringToElement(message))\n\
552+
\ (ReasonReact.string(message))\n\
553553
\ </button>\n\
554554
\ <button onClick=(_event => self.send(Toggle))>\n\
555-
\ (ReasonReact.stringToElement(\"Toggle greeting\"))\n\
555+
\ (ReasonReact.string(\"Toggle greeting\"))\n\
556556
\ </button>\n\
557-
\ (\n\
558-
\ self.state.show ?\n\
559-
\ ReasonReact.stringToElement(greeting) : ReasonReact.nullElement\n\
560-
\ )\n\
557+
\ (self.state.show ? ReasonReact.string(greeting) : ReasonReact.null)\n\
561558
\ </div>;\n\
562559
\ },\n\
563560
};\n\
@@ -583,7 +580,7 @@ let root = OCamlRes.Res.([
583580
\ ...component,\n\
584581
\ render: self =>\n\
585582
\ <div onClick=(self.handle(handleClick))>\n\
586-
\ (ReasonReact.stringToElement(message))\n\
583+
\ (ReasonReact.string(message))\n\
587584
\ </div>,\n\
588585
};\n\
589586
")]) ;
@@ -598,6 +595,7 @@ let root = OCamlRes.Res.([
598595
# in another tab\n\
599596
npm run webpack\n\
600597
```\n\
598+
\n\
601599
After you see the webpack compilation succeed (the `npm run webpack` step), open up `src/index.html` (**no server needed!**). Then modify whichever `.re` file in `src` and refresh the page to see the changes.\n\
602600
\n\
603601
**For more elaborate ReasonReact examples**, please see https://github.com/reasonml-community/reason-react-example\n\
@@ -633,7 +631,7 @@ let root = OCamlRes.Res.([
633631
\ \"dependencies\": {\n\
634632
\ \"react\": \"^16.2.0\",\n\
635633
\ \"react-dom\": \"^16.2.0\",\n\
636-
\ \"reason-react\": \">=0.3.4\"\n\
634+
\ \"reason-react\": \">=0.4.0\"\n\
637635
\ },\n\
638636
\ \"devDependencies\": {\n\
639637
\ \"bs-platform\": \"^${bsb:bs-version}\",\n\
@@ -665,10 +663,7 @@ let root = OCamlRes.Res.([
665663
\ \"bs-dependencies\": [\n\
666664
\ \"reason-react\"\n\
667665
\ ],\n\
668-
\ \"refmt\": 3,\n\
669-
\ \"warnings\": {\n\
670-
\ \"error\": \"+5\"\n\
671-
\ }\n\
666+
\ \"refmt\": 3\n\
672667
}\n\
673668
") ;
674669
File (".gitignore",

jscomp/ounit_tests/ounit_cmd_tests.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,13 @@ external ff :
243243
OUnit.assert_bool __LOC__
244244
(Ext_string.contain_substring should_err.stderr "contravariant")
245245
end;
246-
__LOC__ >:: begin fun _ ->
246+
(* __LOC__ >:: begin fun _ ->
247247
let should_err = bsc_check_eval {|
248248
type 'a t = {k : int -> 'a } [@@bs.deriving abstract]
249249
|} in
250250
OUnit.assert_bool __LOC__
251251
(Ext_string.contain_substring should_err.stderr "not allowed")
252-
end
252+
end *)
253253
(* __LOC__ >:: begin fun _ -> *)
254254
(* let should_infer = perform_bsc [| "-i"; "-bs-eval"|] {| *)
255255
(* let f = fun [@bs] x -> let (a,b) = x in a + b *)

jscomp/syntax/ast_attributes.ml

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,38 @@ let iter_process_derive_type attrs =
190190
!st
191191

192192

193-
let process_bs_string_int_unwrap_uncurry attrs =
193+
(* duplicated [bs.uncurry] [bs.string] not allowed,
194+
it is worse in bs.uncurry since it will introduce
195+
inconsistency in arity
196+
*)
197+
let iter_process_bs_string_int_unwrap_uncurry attrs =
198+
let st = ref `Nothing in
199+
let assign v (({loc;_}, _ ) as attr : attr) =
200+
if !st = `Nothing then
201+
begin
202+
Bs_ast_invariant.mark_used_bs_attribute attr;
203+
st := v ;
204+
end
205+
else Bs_syntaxerr.err loc Conflict_attributes in
206+
List.iter
207+
(fun (({txt ; loc}, (payload : _ ) ) as attr : attr) ->
208+
match txt with
209+
| "bs.string"
210+
-> assign `String attr
211+
| "bs.int"
212+
-> assign `Int attr
213+
| "bs.ignore"
214+
-> assign `Ignore attr
215+
| "bs.unwrap"
216+
-> assign `Unwrap attr
217+
| "bs.uncurry"
218+
->
219+
assign (`Uncurry (Ast_payload.is_single_int payload)) attr
220+
| _ -> ()
221+
) attrs;
222+
!st
223+
224+
(* let process_bs_string_int_unwrap_uncurry attrs =
194225
List.fold_left
195226
(fun (st,attrs)
196227
(({txt ; loc}, (payload : _ ) ) as attr : attr) ->
@@ -216,7 +247,7 @@ let process_bs_string_int_unwrap_uncurry attrs =
216247
->
217248
Bs_syntaxerr.err loc Conflict_attributes
218249
| _ , _ -> st, (attr :: attrs )
219-
) (`Nothing, []) attrs
250+
) (`Nothing, []) attrs *)
220251

221252

222253
let iter_process_bs_string_as (attrs : t) : string option =
@@ -327,6 +358,20 @@ let bs_obj : attr
327358
let bs_get : attr
328359
= {txt = "bs.get"; loc = locg}, Ast_payload.empty
329360

361+
let bs_get_arity : attr
362+
= {txt = "internal.arity"; loc = locg},
363+
PStr
364+
[{pstr_desc =
365+
Pstr_eval (
366+
{pexp_desc =
367+
Pexp_constant
368+
(Const_int 1);
369+
pexp_loc = locg;
370+
pexp_attributes = []
371+
},[])
372+
; pstr_loc = locg}]
373+
374+
330375
let bs_set : attr
331376
= {txt = "bs.set"; loc = locg}, Ast_payload.empty
332377

jscomp/syntax/ast_attributes.mli

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@ type derive_attr = {
4646
explict_nonrec : bool;
4747
bs_deriving : Ast_payload.action list option
4848
}
49-
val process_bs_string_int_unwrap_uncurry :
50-
t -> [`Nothing | `String | `Int | `Ignore | `Unwrap | `Uncurry of int option ] * t
49+
50+
51+
val iter_process_bs_string_int_unwrap_uncurry :
52+
t ->
53+
[`Nothing | `String | `Int | `Ignore | `Unwrap | `Uncurry of int option ]
5154

5255

5356
val iter_process_bs_string_as :
@@ -82,5 +85,6 @@ val bs_obj : attr
8285

8386

8487
val bs_get : attr
88+
val bs_get_arity : attr
8589
val bs_set : attr
8690
val bs_return_undefined : attr

jscomp/syntax/ast_derive_abstract.ml

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,15 @@ let handle_config (config : Parsetree.expression option) =
3434
U.invalid_config config
3535
| None -> ()
3636

37-
(* see #2337
38-
TODO: relax it to allow (int -> int [@bs])
39-
*)
40-
let rec checkNotFunciton (ty : Parsetree.core_type) =
41-
match ty.ptyp_desc with
42-
| Ptyp_poly (_,ty) -> checkNotFunciton ty
43-
| Ptyp_alias (ty,_) -> checkNotFunciton ty
44-
| Ptyp_arrow _ ->
45-
Location.raise_errorf
46-
~loc:ty.ptyp_loc
47-
"syntactic function type is not allowed when working with abstract bs.deriving, create a named type as work around"
48-
| Ptyp_any
49-
| Ptyp_var _
50-
| Ptyp_tuple _
51-
| Ptyp_constr _
52-
| Ptyp_object _
53-
| Ptyp_class _
54-
| Ptyp_variant _
55-
| Ptyp_package _
56-
| Ptyp_extension _ -> ()
5737

5838

5939
let get_optional_attrs =
6040
[Ast_attributes.bs_get; Ast_attributes.bs_return_undefined]
61-
let get_attrs = [ Ast_attributes.bs_get ]
41+
(** For this attributes, its type was wrapped as an option,
42+
so we can still reuse existing frame work
43+
*)
44+
45+
let get_attrs = [ Ast_attributes.bs_get_arity]
6246
let set_attrs = [Ast_attributes.bs_set]
6347
let handleTdcl (tdcl : Parsetree.type_declaration) =
6448
let core_type = U.core_type_of_type_declaration tdcl in
@@ -88,31 +72,38 @@ let handleTdcl (tdcl : Parsetree.type_declaration) =
8872
pld_loc
8973
}:
9074
Parsetree.label_declaration) (acc, maker, labels) ->
91-
let () = checkNotFunciton pld_type in
92-
(* TODO: explain why *)
93-
let prim, newLabel =
75+
let prim_as_name, newLabel =
9476
match Ast_attributes.iter_process_bs_string_as pld_attributes with
9577
| None ->
96-
[label_name], pld_name
78+
label_name, pld_name
9779
| Some new_name ->
98-
[new_name], {pld_name with txt = new_name}
80+
new_name, {pld_name with txt = new_name}
9981
in
100-
let is_option = Ast_attributes.has_bs_optional pld_attributes in
101-
let maker, getter_type =
102-
if is_option then
82+
let prim = [prim_as_name] in
83+
let is_optional = Ast_attributes.has_bs_optional pld_attributes in
84+
let maker, getter_declaration =
85+
if is_optional then
10386
let optional_type = Ast_core_type.lift_option_type pld_type in
104-
Ast_core_type.opt_arrow pld_loc label_name optional_type maker,
105-
Typ.arrow ~loc "" core_type optional_type
87+
(Ast_core_type.opt_arrow pld_loc label_name optional_type maker,
88+
Val.mk pld_name
89+
~attrs:get_optional_attrs ~prim
90+
(Typ.arrow ~loc "" core_type optional_type)
91+
)
10692
else
10793
Typ.arrow ~loc:pld_loc label_name pld_type maker,
108-
Typ.arrow ~loc "" core_type pld_type
94+
Val.mk pld_name ~attrs:get_attrs
95+
~prim:(
96+
["" ; (* Not needed actually*)
97+
External_ffi_types.to_string
98+
(Ffi_bs (
99+
[{arg_type = Nothing; arg_label = External_arg_spec.empty_label}],
100+
Return_identity,
101+
Js_get {js_get_name = prim_as_name; js_get_scopes = []}
102+
))] )
103+
(Typ.arrow ~loc "" core_type pld_type)
109104
in
110105
let acc =
111-
Val.mk pld_name
112-
~attrs:(
113-
if is_option then get_optional_attrs
114-
else get_attrs)
115-
~prim getter_type :: acc in
106+
getter_declaration :: acc in
116107
let is_current_field_mutable = pld_mutable = Mutable in
117108
let acc =
118109
if is_current_field_mutable then
@@ -130,7 +121,7 @@ let handleTdcl (tdcl : Parsetree.type_declaration) =
130121
else acc in
131122
acc,
132123
maker,
133-
(is_option, newLabel)::labels
124+
(is_optional, newLabel)::labels
134125
) label_declarations
135126
([],
136127
(if has_optional_field then

0 commit comments

Comments
 (0)