Skip to content

Commit 157fca2

Browse files
committed
first pass at tagged templates
basically kevinbarabash#2 rebased on master
1 parent 3bb11b4 commit 157fca2

36 files changed

+417
-68
lines changed

jscomp/core/j.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ and expression_desc =
115115
This can be constructed either in a static way [E.array_index_by_int] or a dynamic way
116116
[E.array_index]
117117
*)
118+
| Tagged_template of expression * expression list * expression list
118119
| Static_index of expression * string * int32 option
119120
(* The third argument bool indicates whether we should
120121
print it as

jscomp/core/js_analyzer.ml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ let rec no_side_effect_expression_desc (x : J.expression_desc) =
103103
| String_append (a, b) | Seq (a, b) -> no_side_effect a && no_side_effect b
104104
| Length (e, _) | Caml_block_tag (e, _) | Typeof e -> no_side_effect e
105105
| Bin (op, a, b) -> op <> Eq && no_side_effect a && no_side_effect b
106+
(*
107+
TODO: we should check look at each of the expressions in the 'values' list/array
108+
to determine if any of them have side-effects. For now we'll just return false
109+
to make the compiler happy.
110+
*)
111+
| Tagged_template _ -> false
106112
| Js_not _ | Cond _ | FlatCall _ | Call _ | New _ | Raw_js_code _
107113
(* actually true? *) ->
108114
false
@@ -204,7 +210,7 @@ let rec eq_expression ({ expression_desc = x0 } : J.expression)
204210
| _ -> false)
205211
| Length _ | Is_null_or_undefined _ | String_append _ | Typeof _ | Js_not _
206212
| Cond _ | FlatCall _ | New _ | Fun _ | Raw_js_code _ | Array _
207-
| Caml_block_tag _ | Object _
213+
| Caml_block_tag _ | Object _ | Tagged_template _
208214
| Number (Uint _) ->
209215
false
210216
| Await _ -> false

jscomp/core/js_dump.ml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ let exp_need_paren (e : J.expression) =
147147
match e.expression_desc with
148148
(* | Caml_uninitialized_obj _ *)
149149
| Call ({ expression_desc = Fun _ | Raw_js_code _ }, _, _) -> true
150+
(* TODO: implement this *)
151+
| Tagged_template _ -> false
150152
| Raw_js_code { code_info = Exp _ }
151153
| Fun _
152154
| Caml_block
@@ -596,6 +598,29 @@ and expression_desc cxt ~(level : int) f x : cxt =
596598
P.string f L.null;
597599
comma_sp f;
598600
expression ~level:1 cxt f el))
601+
| Tagged_template (callExpr, stringArgs, valueArgs) ->
602+
let cxt = expression cxt ~level f callExpr in
603+
P.string f "`";
604+
let rec aux cxt xs ys = match xs, ys with
605+
| [], [] -> ()
606+
| x_head :: x_rest, ys ->
607+
let cxt = (match x_head with
608+
| {J.expression_desc = Str { txt; _ }} ->
609+
P.string f txt;
610+
cxt
611+
| _ ->
612+
P.string f "${";
613+
let cxt = expression cxt ~level f x_head in
614+
P.string f "}";
615+
cxt
616+
)
617+
in
618+
aux cxt ys x_rest
619+
| _ -> assert false
620+
in
621+
aux cxt stringArgs valueArgs;
622+
P.string f "`";
623+
cxt
599624
| String_index (a, b) ->
600625
P.group f 1 (fun _ ->
601626
let cxt = expression ~level:15 cxt f a in

jscomp/core/js_exp_make.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ let call ?comment ~info e0 args : t =
7272
let flat_call ?comment e0 es : t =
7373
{ expression_desc = FlatCall (e0, es); comment }
7474

75+
let tagged_template ?comment callExpr stringArgs valueArgs : t =
76+
{ expression_desc = Tagged_template (callExpr, stringArgs, valueArgs); comment }
77+
7578
let runtime_var_dot ?comment (x : string) (e1 : string) : J.expression =
7679
{
7780
expression_desc =

jscomp/core/js_exp_make.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ val call : ?comment:string -> info:Js_call_info.t -> t -> t list -> t
279279

280280
val flat_call : ?comment:string -> t -> t -> t
281281

282+
val tagged_template : ?comment:string -> t -> t list -> t list -> t
283+
282284
val new_ : ?comment:string -> J.expression -> J.expression list -> t
283285

284286
val array : ?comment:string -> J.mutable_flag -> J.expression list -> t

jscomp/core/js_fold.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ class fold =
124124
let _self = _self#expression _x0 in
125125
let _self = list (fun _self -> _self#expression) _self _x1 in
126126
_self
127+
| Tagged_template (_, _, _) ->
128+
_self
127129
| String_index (_x0, _x1) ->
128130
let _self = _self#expression _x0 in
129131
let _self = _self#expression _x1 in

jscomp/core/js_record_fold.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ let expression_desc : 'a. ('a, expression_desc) fn =
130130
let st = _self.expression _self st _x0 in
131131
let st = list _self.expression _self st _x1 in
132132
st
133+
| Tagged_template (_, _, _) ->
134+
(* TODO: implement this *)
135+
st
133136
| String_index (_x0, _x1) ->
134137
let st = _self.expression _self st _x0 in
135138
let st = _self.expression _self st _x1 in

jscomp/core/js_record_iter.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ let expression_desc : expression_desc fn =
107107
| Call (_x0, _x1, _x2) ->
108108
_self.expression _self _x0;
109109
list _self.expression _self _x1
110+
| Tagged_template (exprCall, _, _) ->
111+
(* TODO: implement this *)
112+
_self.expression _self exprCall;
110113
| String_index (_x0, _x1) ->
111114
_self.expression _self _x0;
112115
_self.expression _self _x1

jscomp/core/js_record_map.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ let expression_desc : expression_desc fn =
130130
let _x0 = _self.expression _self _x0 in
131131
let _x1 = list _self.expression _self _x1 in
132132
Call (_x0, _x1, _x2)
133+
| Tagged_template (callExpr, stringsArray, valuesArray) ->
134+
(* TODO: implement this *)
135+
Tagged_template (callExpr, stringsArray, valuesArray)
133136
| String_index (_x0, _x1) ->
134137
let _x0 = _self.expression _self _x0 in
135138
let _x1 = _self.expression _self _x1 in

jscomp/core/lam.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type apply_status = App_na | App_infer_full | App_uncurry
2828
type ap_info = {
2929
ap_loc : Location.t;
3030
ap_inlined : Lambda.inline_attribute;
31+
ap_tagged_template : bool;
3132
ap_status : apply_status;
3233
}
3334

jscomp/core/lam.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type apply_status = App_na | App_infer_full | App_uncurry
2727
type ap_info = {
2828
ap_loc : Location.t;
2929
ap_inlined : Lambda.inline_attribute;
30+
ap_tagged_template : bool;
3031
ap_status : apply_status;
3132
}
3233

jscomp/core/lam_analysis.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ let rec no_side_effects (lam : Lam.t) : bool =
9898
true
9999
| Pjs_apply | Pjs_runtime_apply | Pjs_call _ | Pinit_mod | Pupdate_mod
100100
| Pjs_unsafe_downgrade _ | Pdebugger | Pvoid_run | Pfull_apply
101-
| Pjs_fn_method
101+
| Pjs_fn_method | Pjs_tagged_template _
102102
(* TODO *)
103103
| Praw_js_code _ | Pbytessetu | Pbytessets
104104
(* Operations on boxed integers (Nativeint.t, Int32.t, Int64.t) *)

jscomp/core/lam_compile.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,6 +1599,7 @@ and compile_prim (prim_info : Lam.prim_info)
15991599
{
16001600
ap_loc = loc;
16011601
ap_inlined = Default_inline;
1602+
ap_tagged_template = false;
16021603
ap_status = App_uncurry;
16031604
})
16041605
(*FIXME: should pass info down: `f a [@bs][@inlined]`*)

jscomp/core/lam_compile_external_call.mli

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ val translate_ffi :
3636
J.expression list ->
3737
J.expression
3838

39+
val translate_scoped_module_val :
40+
External_ffi_types.external_module_name option ->
41+
string ->
42+
string list ->
43+
J.expression
44+
3945
(** TODO: document supported attributes
4046
Attributes starting with `js` are reserved
4147
examples: "variadic"

jscomp/core/lam_compile_primitive.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,21 @@ let translate output_prefix loc (cxt : Lam_compile_context.t)
339339
| Pjs_object_create _ -> assert false
340340
| Pjs_call { arg_types; ffi } ->
341341
Lam_compile_external_call.translate_ffi cxt arg_types ffi args
342+
| Pjs_tagged_template { ffi } -> (
343+
(* TODO: extract this into lam_compile_external_call.ml *)
344+
let fn = match ffi with
345+
| Js_call { external_module_name; name; scopes } ->
346+
Lam_compile_external_call.translate_scoped_module_val external_module_name name scopes
347+
| _ -> assert false
348+
in
349+
match args with
350+
| [ stringArgs; valueArgs ] -> (
351+
match (stringArgs, valueArgs) with
352+
| ({expression_desc = Array (strings, _)}, {expression_desc = Array (values, _)}) ->
353+
E.tagged_template fn strings values
354+
| _ -> assert false
355+
)
356+
| _ -> assert false)
342357
(* FIXME, this can be removed later *)
343358
| Pisint -> E.is_type_number (Ext_list.singleton_exn args)
344359
| Pis_poly_var_block -> E.is_type_object (Ext_list.singleton_exn args)

jscomp/core/lam_convert.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,11 +512,11 @@ let convert (exports : Set_ident.t) (lam : Lambda.lambda) :
512512
match lam with
513513
| Lvar x -> Lam.var (Hash_ident.find_default alias_tbl x x)
514514
| Lconst x -> Lam.const (Lam_constant_convert.convert_constant x)
515-
| Lapply { ap_func = fn; ap_args = args; ap_loc = loc; ap_inlined } ->
515+
| Lapply { ap_func = fn; ap_args = args; ap_loc = loc; ap_inlined; ap_tagged_template } ->
516516
(* we need do this eargly in case [aux fn] add some wrapper *)
517517
Lam.apply (convert_aux fn)
518518
(Ext_list.map args convert_aux)
519-
{ ap_loc = loc; ap_inlined; ap_status = App_na }
519+
{ ap_loc = loc; ap_inlined; ap_tagged_template; ap_status = App_na }
520520
| Lfunction { params; body; attr } ->
521521
let new_map, body =
522522
rename_optional_parameters Map_ident.empty params body
@@ -685,13 +685,15 @@ let convert (exports : Set_ident.t) (lam : Lambda.lambda) :
685685
{
686686
ap_loc = outer_loc;
687687
ap_inlined = ap_info.ap_inlined;
688+
ap_tagged_template = ap_info.ap_tagged_template;
688689
ap_status = App_na;
689690
}
690691
| _ ->
691692
Lam.apply f [ x ]
692693
{
693694
ap_loc = outer_loc;
694695
ap_inlined = Default_inline;
696+
ap_tagged_template = false;
695697
ap_status = App_na;
696698
}
697699
and convert_switch (e : Lambda.lambda) (s : Lambda.lambda_switch) =

jscomp/core/lam_eta_conversion.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ let transform_under_supply n ap_info fn args =
111111
let unsafe_adjust_to_arity loc ~(to_ : int) ?(from : int option) (fn : Lam.t) :
112112
Lam.t =
113113
let ap_info : Lam.ap_info =
114-
{ ap_loc = loc; ap_inlined = Default_inline; ap_status = App_na }
114+
{ ap_loc = loc; ap_inlined = Default_inline; ap_tagged_template = false; ap_status = App_na }
115115
in
116116
let is_async_fn = match fn with
117117
| Lfunction { attr = {async}} -> async

jscomp/core/lam_pass_remove_alias.ml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t =
198198

199199
(* Ext_log.dwarn __LOC__ "%s/%d" v.name v.stamp; *)
200200
let ap_args = Ext_list.map ap_args simpl in
201-
let[@local] normal () = Lam.apply (simpl fn) ap_args ap_info in
201+
(* todo bring back local inlining *)
202+
let normal () = Lam.apply (simpl fn) ap_args ap_info in
202203
match Hash_ident.find_opt meta.ident_tbl v with
203204
| Some
204205
(FunctionId
@@ -238,7 +239,7 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t =
238239
Lam_closure.is_closed_with_map meta.export_idents params body
239240
in
240241
let is_export_id = Set_ident.mem meta.export_idents v in
241-
match (is_export_id, param_map) with
242+
let result = match (is_export_id, param_map) with
242243
| false, (_, param_map) | true, (true, param_map) -> (
243244
match rec_flag with
244245
| Lam_rec ->
@@ -256,6 +257,18 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t =
256257
(Lam_beta_reduce.propagate_beta_reduce_with_map meta
257258
param_map params body ap_args))
258259
| _ -> normal ()
260+
in
261+
let result = (match result with
262+
| Lprim {primitive; args; loc} -> (match primitive with
263+
(* Converts Pjs_calls to Pjs_tagged_templates if ap_tagged_template is true *)
264+
| Pjs_call {prim_name; ffi} when ap_info.ap_tagged_template ->
265+
let prim = Lam_primitive.Pjs_tagged_template {prim_name; ffi} in
266+
Lam.prim ~primitive:prim ~args loc
267+
| _ -> result
268+
)
269+
| _ -> result)
270+
in
271+
result
259272
else normal ()
260273
else normal ()
261274
| Some _ | None -> normal ())

jscomp/core/lam_primitive.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ type t =
4949
arg_types : External_arg_spec.params;
5050
ffi : External_ffi_types.external_spec;
5151
}
52+
| Pjs_tagged_template of {
53+
prim_name : string;
54+
ffi : External_ffi_types.external_spec;
55+
}
5256
| Pjs_object_create of External_arg_spec.obj_params
5357
(* Exceptions *)
5458
| Praise
@@ -259,6 +263,11 @@ let eq_primitive_approx (lhs : t) (rhs : t) =
259263
match rhs with
260264
| Pjs_object_create obj_create1 -> obj_create = obj_create1
261265
| _ -> false)
266+
| Pjs_tagged_template { prim_name; ffi } -> (
267+
match rhs with
268+
| Pjs_tagged_template rhs ->
269+
prim_name = rhs.prim_name && ffi = rhs.ffi
270+
| _ -> false)
262271
| Pintcomp comparison -> (
263272
match rhs with
264273
| Pintcomp comparison1 -> Lam_compat.eq_comparison comparison comparison1

jscomp/core/lam_primitive.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ type t =
4444
arg_types : External_arg_spec.params;
4545
ffi : External_ffi_types.external_spec;
4646
}
47+
| Pjs_tagged_template of {
48+
prim_name : string;
49+
ffi : External_ffi_types.external_spec;
50+
}
4751
| Pjs_object_create of External_arg_spec.obj_params
4852
| Praise
4953
| Psequand

jscomp/core/lam_print.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ let primitive ppf (prim : Lam_primitive.t) =
9393
| Plazyforce -> fprintf ppf "force"
9494
| Pccall p -> fprintf ppf "%s" p.prim_name
9595
| Pjs_call { prim_name } -> fprintf ppf "%s[js]" prim_name
96+
| Pjs_tagged_template { prim_name } -> fprintf ppf "%s[js.tagged_template]" prim_name
9697
| Pjs_object_create _ -> fprintf ppf "[js.obj]"
9798
| Praise -> fprintf ppf "raise"
9899
| Psequand -> fprintf ppf "&&"
@@ -263,12 +264,13 @@ let lambda ppf v =
263264
| Lvar id -> Ident.print ppf id
264265
| Lglobal_module (id, dynamic_import) -> fprintf ppf (if dynamic_import then "dynamic global %a" else "global %a") Ident.print id
265266
| Lconst cst -> struct_const ppf cst
266-
| Lapply { ap_func; ap_args; ap_info = { ap_inlined } } ->
267+
| Lapply { ap_func; ap_args; ap_info = { ap_inlined; ap_tagged_template } } ->
267268
let lams ppf args =
268269
List.iter (fun l -> fprintf ppf "@ %a" lam l) args
269270
in
270-
fprintf ppf "@[<2>(apply%s@ %a%a)@]"
271+
fprintf ppf "@[<2>(apply%s%s@ %a%a)@]"
271272
(match ap_inlined with Always_inline -> "%inlned" | _ -> "")
273+
(match ap_tagged_template with true -> "%tagged_template" | _ -> "")
272274
lam ap_func lams ap_args
273275
| Lfunction { params; body; _ } ->
274276
let pr_params ppf params =

jscomp/ml/lambda.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ and lambda_apply =
307307
ap_args : lambda list;
308308
ap_loc : Location.t;
309309
ap_inlined : inline_attribute;
310+
ap_tagged_template : bool;
310311
}
311312

312313
and lambda_switch =
@@ -641,12 +642,13 @@ let rec map f lam =
641642
| Lvar _ -> lam
642643
| Lconst _ -> lam
643644
| Lapply { ap_func; ap_args; ap_loc;
644-
ap_inlined; } ->
645+
ap_inlined; ap_tagged_template; } ->
645646
Lapply {
646647
ap_func = map f ap_func;
647648
ap_args = List.map (map f) ap_args;
648649
ap_loc;
649-
ap_inlined;
650+
ap_inlined;
651+
ap_tagged_template ;
650652
}
651653
| Lfunction { params; body; attr; loc; } ->
652654
Lfunction { params; body = map f body; attr; loc; }

jscomp/ml/lambda.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ and lambda_apply =
309309
ap_args : lambda list;
310310
ap_loc : Location.t;
311311
ap_inlined : inline_attribute; (* specified with the [@inlined] attribute *)
312+
ap_tagged_template : bool;
312313
}
313314

314315
and lambda_switch =

jscomp/ml/matching.ml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,13 @@ let code_force =
15271527

15281528

15291529
let inline_lazy_force arg loc =
1530-
Lapply { ap_func = Lazy.force code_force; ap_inlined = Default_inline; ap_args = [arg]; ap_loc = loc}
1530+
Lapply {
1531+
ap_func = Lazy.force code_force;
1532+
ap_inlined = Default_inline;
1533+
ap_tagged_template = false;
1534+
ap_args = [arg];
1535+
ap_loc = loc;
1536+
}
15311537
let make_lazy_matching def = function
15321538
[] -> fatal_error "Matching.make_lazy_matching"
15331539
| (arg,_mut) :: argl ->

0 commit comments

Comments
 (0)