Skip to content

Commit ae464d3

Browse files
committed
Support @new @variadic
Signed-off-by: Yuta Sato <[email protected]>
1 parent cf8ff3b commit ae464d3

7 files changed

+60
-10
lines changed

jscomp/core/lam_compile_external_call.ml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ let splice_fn_apply fn args =
3030
E.runtime_call Js_runtime_modules.caml_splice_call "spliceApply"
3131
[ fn; E.array Immutable args ]
3232

33+
let splice_fn_new_apply fn args =
34+
E.runtime_call Js_runtime_modules.caml_splice_call "spliceNewApply"
35+
[ fn; E.array Immutable args ]
36+
3337
let splice_obj_fn_apply obj name args =
3438
E.runtime_call Js_runtime_modules.caml_splice_call "spliceObjApply"
3539
[ obj; E.str name; E.array Immutable args ]
@@ -271,7 +275,7 @@ let translate_ffi (cxt : Lam_compile_context.t) arg_types
271275
let args, eff = assemble_args_no_splice arg_types args in
272276
(* TODO: fix in rest calling convention *)
273277
add_eff eff (E.call ~info:{ arity = Full; call_info = Call_na } fn args)
274-
| Js_new { external_module_name = module_name; name = fn; scopes } ->
278+
| Js_new { external_module_name = module_name; name = fn; splice; scopes } ->
275279
(* handle [@@new]*)
276280
(* This has some side effect, it will
277281
mark its identifier (If it has) as an object,
@@ -281,15 +285,24 @@ let translate_ffi (cxt : Lam_compile_context.t) arg_types
281285
TODO: we should propagate this property
282286
as much as we can(in alias table)
283287
*)
284-
let args, eff = assemble_args_no_splice arg_types args in
285-
let fn = translate_scoped_module_val module_name fn scopes in
286-
add_eff eff
287-
((match cxt.continuation with
288+
let mark () =
289+
match cxt.continuation with
288290
| Declare (_, id) | Assign id ->
289291
(* Format.fprintf Format.err_formatter "%a@."Ident.print id; *)
290292
Ext_ident.make_js_object id
291-
| EffectCall _ | NeedValue _ -> ());
292-
E.new_ fn args)
293+
| EffectCall _ | NeedValue _ -> ()
294+
in
295+
let fn = translate_scoped_module_val module_name fn scopes in
296+
if splice then
297+
let args, eff, dynamic = assemble_args_has_splice arg_types args in
298+
add_eff eff
299+
(mark ();
300+
if dynamic then splice_fn_new_apply fn args
301+
else E.new_ fn args)
302+
else
303+
let args, eff = assemble_args_no_splice arg_types args in
304+
add_eff eff
305+
(mark (); E.new_ fn args)
293306
| Js_send { splice; name; js_send_scopes } -> (
294307
match args with
295308
| self :: args ->

jscomp/frontend/ast_external_process.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -800,12 +800,12 @@ let external_desc_of_non_obj (loc : Location.t) (st : external_desc)
800800
val_send = None;
801801
set_name = None;
802802
get_name = None;
803-
splice = false;
803+
splice;
804804
scopes;
805805
mk_obj = _;
806806
return_wrapper = _;
807807
} ->
808-
Js_new { name; external_module_name; scopes }
808+
Js_new { name; external_module_name; splice; scopes }
809809
| { new_name = Some _; _ } ->
810810
Bs_syntaxerr.err loc
811811
(Conflict_ffi_attribute "Attribute found that conflicts with %@new")

jscomp/frontend/external_ffi_types.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type external_spec =
5858
| Js_new of {
5959
name : string;
6060
external_module_name : external_module_name option;
61+
splice : bool;
6162
scopes : string list;
6263
}
6364
| Js_set of { js_set_name : string; js_set_scopes : string list }

jscomp/frontend/external_ffi_types.pp.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type external_spec =
7171
| Js_new of {
7272
name : string ;
7373
external_module_name : external_module_name option;
74+
splice : bool ;
7475
scopes : string list;
7576
}
7677
| Js_set of {
@@ -223,7 +224,7 @@ let check_ffi ?loc ffi : bool =
223224
->
224225
upgrade (is_package_relative_path external_module_name.bundle);
225226
check_external_module_name external_module_name
226-
| Js_new {external_module_name ; name; scopes = _}
227+
| Js_new {external_module_name ; name; splice = _; scopes = _}
227228
| Js_call {external_module_name ; name ; splice = _; scopes = _ }
228229
->
229230
Ext_option.iter external_module_name (fun external_module_name ->

jscomp/runtime/caml_splice_call.ml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ let spliceApply : obj -> obj -> obj = [%raw{|function(fn,args){
3838
return fn.apply(null,applied)
3939
}|}]
4040

41+
let spliceNewApply : obj -> obj -> obj = [%raw{|function (ctor,args){
42+
var i, argLen;
43+
argLen = args.length
44+
var applied = []
45+
for(i = 0; i < argLen - 1; ++i){
46+
applied.push(args[i])
47+
}
48+
var lastOne = args[argLen - 1]
49+
for(i = 0; i < lastOne.length; ++i ){
50+
applied.push(lastOne[i])
51+
}
52+
return new ctor(...applied)
53+
}|}]
54+
4155
let spliceObjApply : obj -> obj -> obj -> obj = [%raw{|function(obj,name,args){
4256
var i, argLen;
4357
argLen = args.length

jscomp/runtime/caml_splice_call.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ type obj = Obj.t
2727

2828
val spliceApply : obj -> obj -> obj
2929

30+
val spliceNewApply : obj -> obj -> obj
31+
3032
val spliceObjApply : obj -> obj -> obj -> obj

jscomp/test/splice_test.ml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@ let dynamic arr =
3737
;; dynamic [||]
3838
;; dynamic [|1;1;3|]
3939

40+
(* Array constructor with a single parameter `x`
41+
just makes an array with its length set to `x`,
42+
so at least two parameters are needed
43+
*)
44+
external newArr : int -> int -> int array -> int array = "Array"
45+
[@@bs.splice] [@@bs.new]
46+
47+
let () =
48+
let a = newArr 1 2 [|3;4|] in
49+
eq __LOC__ a [|1;2;3;4|]
50+
51+
let dynamicNew arr =
52+
let a = newArr 1 2 arr in
53+
eq __LOC__ a (Array.concat [[|1; 2|]; arr])
54+
55+
;; dynamicNew [|3;4|]
56+
;; dynamicNew [||]
57+
;; dynamicNew [|1;3|]
58+
4059
module Pipe = struct
4160
external push : int array -> int -> int array -> unit =
4261
"push" [@@send] [@@bs.splice]

0 commit comments

Comments
 (0)