Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions analysis/src/Utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ let identifyPexp pexp =
| Pexp_open _ -> "Pexp_open"
| Pexp_await _ -> "Pexp_await"
| Pexp_jsx_element _ -> "Pexp_jsx_element"
| Pexp_template _ -> "Pexp_template"

let identifyPpat pat =
match pat with
Expand Down
1 change: 1 addition & 0 deletions compiler/core/j.ml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ and expression_desc =
This can be constructed either in a static way [E.array_index_by_int] or a dynamic way
[E.array_index]
*)
| Template_literal of expression list * expression list
| Tagged_template of expression * expression list * expression list
| Static_index of expression * string * int32 option
(* The third argument bool indicates whether we should
Expand Down
6 changes: 5 additions & 1 deletion compiler/core/js_analyzer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ let rec no_side_effect_expression_desc (x : J.expression_desc) =
| String_append (a, b) | Seq (a, b) -> no_side_effect a && no_side_effect b
| Length (e, _) | Caml_block_tag (e, _) | Typeof e -> no_side_effect e
| Bin (op, a, b) -> op <> Eq && no_side_effect a && no_side_effect b
| Template_literal (strings, values) ->
Ext_list.for_all strings no_side_effect
&& Ext_list.for_all values no_side_effect
| Tagged_template (call_expr, strings, values) ->
no_side_effect call_expr
&& Ext_list.for_all strings no_side_effect
Expand Down Expand Up @@ -229,7 +232,8 @@ let rec eq_expression ({expression_desc = x0} : J.expression)
| _ -> false)
| Length _ | Is_null_or_undefined _ | String_append _ | Typeof _ | Js_not _
| Js_bnot _ | In _ | Cond _ | FlatCall _ | New _ | Fun _ | Raw_js_code _
| Array _ | Caml_block_tag _ | Object _ | Tagged_template _ | Await _ ->
| Array _ | Caml_block_tag _ | Object _ | Template_literal _
| Tagged_template _ | Await _ ->
false
| Spread _ -> false

Expand Down
18 changes: 18 additions & 0 deletions compiler/core/js_dump.ml
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ let rec exp_need_paren ?(arrow = false) (e : J.expression) =
false
| Await _ -> false
| Spread _ -> false
| Template_literal _ -> false
| Tagged_template _ -> false
| Optional_block (e, true) when arrow -> exp_need_paren ~arrow e
| Optional_block _ -> false
Expand Down Expand Up @@ -713,6 +714,23 @@ and expression_desc cxt ~(level : int) f x : cxt =
aux cxt string_args value_args;
P.string f "`";
cxt
| Template_literal (string_args, value_args) ->
P.string f "`";
let rec aux cxt xs ys =
match (xs, ys) with
| [], [] -> ()
| [{J.expression_desc = Str {txt; _}}], [] -> P.string f txt
| {J.expression_desc = Str {txt; _}} :: x_rest, y :: y_rest ->
P.string f txt;
P.string f "${";
let cxt = expression cxt ~level f y in
P.string f "}";
aux cxt x_rest y_rest
| _ -> assert false
in
aux cxt string_args value_args;
P.string f "`";
cxt
| String_index (a, b) ->
P.group f 1 (fun _ ->
let cxt = expression ~level:15 cxt f a in
Expand Down
3 changes: 3 additions & 0 deletions compiler/core/js_exp_make.ml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ let tagged_template ?comment call_expr string_args value_args : t =
comment;
}

let template_literal ?comment string_args value_args : t =
{expression_desc = Template_literal (string_args, value_args); comment}

let runtime_var_dot ?comment (x : string) (e1 : string) : J.expression =
{
expression_desc =
Expand Down
1 change: 1 addition & 0 deletions compiler/core/js_exp_make.mli
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ val call : ?comment:string -> info:Js_call_info.t -> t -> t list -> t
val flat_call : ?comment:string -> t -> t -> t

val tagged_template : ?comment:string -> t -> t list -> t list -> t
val template_literal : ?comment:string -> t list -> t list -> t

val new_ : ?comment:string -> J.expression -> J.expression list -> t

Expand Down
4 changes: 4 additions & 0 deletions compiler/core/js_fold.ml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ class fold =
let _self = _self#expression _x0 in
let _self = list (fun _self -> _self#expression) _self _x1 in
_self
| Template_literal (_x0, _x1) ->
let _self = list (fun _self -> _self#expression) _self _x0 in
let _self = list (fun _self -> _self#expression) _self _x1 in
_self
| Tagged_template (_x0, _x1, _x2) ->
let _self = _self#expression _x0 in
let _self = list (fun _self -> _self#expression) _self _x1 in
Expand Down
4 changes: 4 additions & 0 deletions compiler/core/js_record_fold.ml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ let expression_desc : 'a. ('a, expression_desc) fn =
let st = _self.expression _self st _x0 in
let st = list _self.expression _self st _x1 in
st
| Template_literal (_x0, _x1) ->
let st = list _self.expression _self st _x0 in
let st = list _self.expression _self st _x1 in
st
| Tagged_template (_xo, _x1, _x2) ->
let st = _self.expression _self st _xo in
let st = list _self.expression _self st _x1 in
Expand Down
3 changes: 3 additions & 0 deletions compiler/core/js_record_iter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ let expression_desc : expression_desc fn =
| Call (_x0, _x1, _x2) ->
_self.expression _self _x0;
list _self.expression _self _x1
| Template_literal (_x0, _x1) ->
list _self.expression _self _x0;
list _self.expression _self _x1
| Tagged_template (_x0, _x1, _x2) ->
_self.expression _self _x0;
list _self.expression _self _x1;
Expand Down
4 changes: 4 additions & 0 deletions compiler/core/js_record_map.ml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ let expression_desc : expression_desc fn =
let _x0 = _self.expression _self _x0 in
let _x1 = list _self.expression _self _x1 in
Call (_x0, _x1, _x2)
| Template_literal (_x0, _x1) ->
let _x0 = list _self.expression _self _x0 in
let _x1 = list _self.expression _self _x1 in
Template_literal (_x0, _x1)
| Tagged_template (_x0, _x1, _x2) ->
let _x0 = _self.expression _self _x0 in
let _x1 = list _self.expression _self _x1 in
Expand Down
2 changes: 1 addition & 1 deletion compiler/core/lam_analysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ let rec no_side_effects (lam : Lam.t) : bool =
| Pbigintcomp _ | Pbigintorder | Pbigintmin | Pbigintmax
(* string primitives *)
| Pstringlength | Pstringrefu | Pstringrefs | Pstringcomp _ | Pstringorder
| Pstringmin | Pstringmax
| Pstringmin | Pstringmax | Pstringtemplate _
(* array primitives *)
| Pmakearray | Parraylength | Parrayrefu | Parrayrefs
(* list primitives *)
Expand Down
3 changes: 3 additions & 0 deletions compiler/core/lam_compile_primitive.ml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ let translate output_prefix loc (cxt : Lam_compile_context.t)
match args with
| [a; b] -> E.string_append a b
| _ -> assert false)
| Pstringtemplate strings ->
let string_args = List.map E.str strings in
E.template_literal string_args args
| Pinit_mod -> E.runtime_call Primitive_modules.module_ "init" args
| Pupdate_mod -> E.runtime_call Primitive_modules.module_ "update" args
| Psome -> (
Expand Down
2 changes: 2 additions & 0 deletions compiler/core/lam_convert.ml
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
| Pstringmin -> prim ~primitive:Pstringmin ~args loc
| Pstringmax -> prim ~primitive:Pstringmax ~args loc
| Pstringadd -> prim ~primitive:Pstringadd ~args loc
| Pstringtemplate strings ->
prim ~primitive:(Pstringtemplate strings) ~args loc
| Pabsfloat -> assert false
| Pstringrefs -> prim ~primitive:Pstringrefs ~args loc
| Pisint -> prim ~primitive:Pisint ~args loc
Expand Down
5 changes: 3 additions & 2 deletions compiler/core/lam_primitive.ml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ type t =
| Pstringrefu
| Pstringrefs
| Pstringadd
| Pstringtemplate of string list
| Pstringcomp of Lam_compat.comparison
| Pstringorder
| Pstringmin
Expand Down Expand Up @@ -213,8 +214,8 @@ let eq_primitive_approx (lhs : t) (rhs : t) =
| Ppowbigint | Pnotbigint | Pandbigint | Porbigint | Pxorbigint | Plslbigint
| Pasrbigint | Pbigintorder | Pbigintmin | Pbigintmax
(* string primitives *)
| Pstringlength | Pstringrefu | Pstringrefs | Pstringadd | Pstringcomp _
| Pstringorder | Pstringmin | Pstringmax
| Pstringlength | Pstringrefu | Pstringrefs | Pstringadd | Pstringtemplate _
| Pstringcomp _ | Pstringorder | Pstringmin | Pstringmax
(* List primitives *)
| Pmakelist
(* dict primitives *)
Expand Down
1 change: 1 addition & 0 deletions compiler/core/lam_primitive.mli
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ type t =
| Pstringrefu
| Pstringrefs
| Pstringadd
| Pstringtemplate of string list
| Pstringcomp of Lam_compat.comparison
| Pstringorder
| Pstringmin
Expand Down
1 change: 1 addition & 0 deletions compiler/core/lam_print.ml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ let primitive ppf (prim : Lam_primitive.t) =
| Pnegint -> fprintf ppf "~-"
| Paddint -> fprintf ppf "+"
| Pstringadd -> fprintf ppf "+*"
| Pstringtemplate _ -> fprintf ppf "template"
| Psubint -> fprintf ppf "-"
| Pmulint -> fprintf ppf "*"
| Pdivint -> fprintf ppf "/"
Expand Down
67 changes: 32 additions & 35 deletions compiler/frontend/ast_attributes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -224,48 +224,45 @@ type as_const_payload = Int of int | Str of string * External_arg_spec.delim

let iter_process_bs_string_or_int_as (attrs : Parsetree.attributes) =
let st = ref None in
let string_payload_loc payload =
match payload with
| Parsetree.PStr [{pstr_desc = Parsetree.Pstr_eval ({pexp_loc; _}, _); _}]
->
Some pexp_loc
| _ -> None
in
Ext_list.iter attrs (fun (({txt; loc}, payload) as attr) ->
match txt with
| "as" ->
if !st = None then (
Used_attributes.mark_used_attribute attr;
match Ast_payload.is_single_int payload with
| None -> (
match payload with
| PStr
[
{
pstr_desc =
Pstr_eval
( {
pexp_desc = Pexp_constant (Pconst_string (s, delim_));
pexp_loc;
_;
},
_ );
_;
};
]
when Ast_utf8_string_interp.parse_processed_delim delim_ <> None
-> (
let delim =
match Ast_utf8_string_interp.parse_processed_delim delim_ with
| None -> assert false
| Some delim -> delim
in
st := Some (Str (s, delim));
if delim = DNoQuotes then
(* check that it is a valid object literal *)
match
Classify_function.classify
~check:(pexp_loc, Bs_flow_ast_utils.flow_deli_offset delim_)
s
with
| Js_literal _ -> ()
| _ ->
Location.raise_errorf ~loc:pexp_loc
"an object literal expected")
| _ -> Bs_syntaxerr.err loc Expect_int_or_string_or_json_literal)
match Ast_payload.is_single_string payload with
| Some (s, delim_) -> (
match Ast_utf8_string_interp.parse_processed_delim delim_ with
| None ->
Bs_syntaxerr.err loc Expect_int_or_string_or_json_literal
| Some delim -> (
let payload_loc =
match string_payload_loc payload with
| Some payload_loc -> payload_loc
| None -> loc
in
st := Some (Str (s, delim));
if delim = DNoQuotes then
(* check that it is a valid object literal *)
match
Classify_function.classify
~check:
(payload_loc, Bs_flow_ast_utils.flow_deli_offset delim_)
s
with
| Js_literal _ -> ()
| _ ->
Location.raise_errorf ~loc:payload_loc
"an object literal expected"))
| None -> Bs_syntaxerr.err loc Expect_int_or_string_or_json_literal)
| Some v -> st := Some (Int v))
else raise (Ast_untagged_variants.Error (loc, Duplicated_bs_as))
| _ -> ());
Expand Down
4 changes: 4 additions & 0 deletions compiler/frontend/bs_ast_mapper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,10 @@ module E = struct
jsx_container_element ~loc ~attrs name (map_jsx_props sub props) ote
(map_jsx_children sub children)
closing_tag
| Pexp_template {tag; prefix; strings; expressions} ->
let tag = map_opt (sub.expr sub) tag in
let expressions = List.map (sub.expr sub) expressions in
template ~loc ~attrs {tag; prefix; strings; expressions}
end

module P = struct
Expand Down
1 change: 1 addition & 0 deletions compiler/ml/ast_helper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ module Exp = struct

let ident ?loc ?attrs a = mk ?loc ?attrs (Pexp_ident a)
let constant ?loc ?attrs a = mk ?loc ?attrs (Pexp_constant a)
let template ?loc ?attrs a = mk ?loc ?attrs (Pexp_template a)
let let_ ?loc ?attrs a b c = mk ?loc ?attrs (Pexp_let (a, b, c))
let fun_ ?loc ?attrs ?(async = false) ~arity a b c d =
mk ?loc ?attrs
Expand Down
1 change: 1 addition & 0 deletions compiler/ml/ast_helper.mli
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ module Exp : sig

val ident : ?loc:loc -> ?attrs:attrs -> lid -> expression
val constant : ?loc:loc -> ?attrs:attrs -> constant -> expression
val template : ?loc:loc -> ?attrs:attrs -> template_literal -> expression
val let_ :
?loc:loc ->
?attrs:attrs ->
Expand Down
3 changes: 3 additions & 0 deletions compiler/ml/ast_iterator.ml
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@ module E = struct
iter_loc sub lid;
sub.expr sub e
| Pexp_extension x -> sub.extension sub x
| Pexp_template {tag; expressions; _} ->
iter_opt (sub.expr sub) tag;
List.iter (sub.expr sub) expressions
| Pexp_await e -> sub.expr sub e
| Pexp_jsx_element (Jsx_fragment {jsx_fragment_children = children}) ->
iter_jsx_children sub children
Expand Down
4 changes: 4 additions & 0 deletions compiler/ml/ast_mapper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ module E = struct
| Pexp_open (ovf, lid, e) ->
open_ ~loc ~attrs ovf (map_loc sub lid) (sub.expr sub e)
| Pexp_extension x -> extension ~loc ~attrs (sub.extension sub x)
| Pexp_template {tag; prefix; strings; expressions} ->
let tag = map_opt (sub.expr sub) tag in
let expressions = List.map (sub.expr sub) expressions in
template ~loc ~attrs {tag; prefix; strings; expressions}
| Pexp_await e -> await ~loc ~attrs (sub.expr sub e)
| Pexp_jsx_element
(Jsx_fragment
Expand Down
Loading
Loading