Skip to content

Commit 8591431

Browse files
Rewrite nested JSX component paths to direct hoisted exports
1 parent ff36aba commit 8591431

26 files changed

Lines changed: 396 additions & 19 deletions

compiler/core/js_of_lam_block.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ let field (field_info : Lam_compat.field_dbg_info) e (i : int32) =
4343
| Fld_cons -> E.cons_access e i
4444
| Fld_record_inline {name} -> E.inline_record_access e name i
4545
| Fld_record {name} -> E.record_access e name i
46-
| Fld_module {name} -> E.module_access e name i
46+
| Fld_module {name; jsx_component = _} -> E.module_access e name i
4747

4848
let field_by_exp e i = E.array_index e i
4949

compiler/core/lam.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,8 @@ let prim ~primitive:(prim : Lam_primitive.t) ~args loc : t =
555555
| ( f :: fields,
556556
Lprim
557557
{
558-
primitive = Pfield (pos, Fld_module {name = f1});
558+
primitive =
559+
Pfield (pos, Fld_module {name = f1; jsx_component = false});
559560
args = [(Lglobal_module (v1, _) | Lvar v1)];
560561
}
561562
:: args ) ->
@@ -566,7 +567,8 @@ let prim ~primitive:(prim : Lam_primitive.t) ~args loc : t =
566567
| ( field1 :: rest,
567568
Lprim
568569
{
569-
primitive = Pfield (pos, Fld_module {name = f1});
570+
primitive =
571+
Pfield (pos, Fld_module {name = f1; jsx_component = false});
570572
args = [((Lglobal_module (v1, _) | Lvar v1) as lam)];
571573
}
572574
:: args1 ) ->

compiler/core/lam_analysis.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,12 @@ let rec no_side_effects (lam : Lam.t) : bool =
123123
(* | Lsend _ -> false *)
124124
| Lapply
125125
{
126-
ap_func = Lprim {primitive = Pfield (_, Fld_module {name = "from_fun"})};
126+
ap_func =
127+
Lprim
128+
{
129+
primitive =
130+
Pfield (_, Fld_module {name = "from_fun"; jsx_component = _});
131+
};
127132
ap_args = [arg];
128133
} ->
129134
no_side_effects arg

compiler/core/lam_arity_analysis.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ let rec get_arity (meta : Lam_stats.t) (lam : Lam.t) : Lam_arity.t =
4242
| Llet (_, _, _, l) -> get_arity meta l
4343
| Lprim
4444
{
45-
primitive = Pfield (_, Fld_module {name});
45+
primitive = Pfield (_, Fld_module {name; jsx_component = _});
4646
args = [Lglobal_module (id, dynamic_import)];
4747
_;
4848
} -> (
@@ -58,7 +58,7 @@ let rec get_arity (meta : Lam_stats.t) (lam : Lam.t) : Lam_arity.t =
5858
[
5959
Lprim
6060
{
61-
primitive = Pfield (_, Fld_module {name});
61+
primitive = Pfield (_, Fld_module {name; jsx_component = _});
6262
args = [Lglobal_module (id, dynamic_import)];
6363
};
6464
];

compiler/core/lam_compat.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ type let_kind = Lambda.let_kind = Strict | Alias | StrictOpt | Variable
6464

6565
type field_dbg_info = Lambda.field_dbg_info =
6666
| Fld_record of {name: string; mutable_flag: Asttypes.mutable_flag}
67-
| Fld_module of {name: string}
67+
| Fld_module of {name: string; jsx_component: bool}
6868
| Fld_record_inline of {name: string}
6969
| Fld_record_extension of {name: string}
7070
| Fld_tuple

compiler/core/lam_compat.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type let_kind = Lambda.let_kind = Strict | Alias | StrictOpt | Variable
2828

2929
type field_dbg_info = Lambda.field_dbg_info =
3030
| Fld_record of {name: string; mutable_flag: Asttypes.mutable_flag}
31-
| Fld_module of {name: string}
31+
| Fld_module of {name: string; jsx_component: bool}
3232
| Fld_record_inline of {name: string}
3333
| Fld_record_extension of {name: string}
3434
| Fld_tuple

compiler/core/lam_compile.ml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,64 @@ type initialization = J.block
232232
*)
233233

234234
let compile output_prefix =
235+
let root_module_name (id : Ident.t) =
236+
match String.index_opt id.name '$' with
237+
| Some index -> String.sub id.name 0 index
238+
| None -> id.name
239+
in
240+
let rec extract_nested_external_component_segments segments
241+
((lam : Lam.t), (make_dynamic_import : bool option ref)) :
242+
(Ident.t * bool * string list) option =
243+
match lam with
244+
| Lprim
245+
{
246+
primitive = Pfield (_, Fld_module {name; jsx_component = _});
247+
args = [arg];
248+
_;
249+
} ->
250+
extract_nested_external_component_segments (name :: segments)
251+
(arg, make_dynamic_import)
252+
| Lvar id ->
253+
make_dynamic_import := Some false;
254+
Some (id, false, List.rev segments)
255+
| Lglobal_module (id, dynamic_import) ->
256+
make_dynamic_import := Some dynamic_import;
257+
Some (id, dynamic_import, List.rev segments)
258+
| _ -> None
259+
in
260+
let extract_nested_external_component_field (lam : Lam.t) :
261+
(Ident.t * bool * string) option =
262+
match lam with
263+
| Lprim
264+
{
265+
primitive = Pfield (_, Fld_module {name = "make"; jsx_component = _});
266+
args = [arg];
267+
_;
268+
} -> (
269+
let dynamic_import = ref None in
270+
match
271+
extract_nested_external_component_segments [] (arg, dynamic_import)
272+
with
273+
| Some (id, dynamic_import, segments) -> (
274+
let segments =
275+
match segments with
276+
| head :: rest
277+
when head = id.name
278+
|| head = root_module_name id
279+
|| Ext_string.starts_with head (root_module_name id ^ "$") ->
280+
rest
281+
| _ -> segments
282+
in
283+
match segments with
284+
| [] -> None
285+
| _ ->
286+
Some
287+
( id,
288+
dynamic_import,
289+
String.concat "$" (root_module_name id :: segments) ))
290+
| None -> None)
291+
| _ -> None
292+
in
235293
let rec compile_external_field (* Like [List.empty]*)
236294
?(dynamic_import = false) (lamba_cxt : Lam_compile_context.t)
237295
(id : Ident.t) name : Js_output.t =
@@ -300,6 +358,17 @@ let compile output_prefix =
300358
(Ext_list.append block args_code, b :: args)
301359
| _ -> assert false)
302360
in
361+
let args =
362+
if appinfo.ap_transformed_jsx then
363+
match (appinfo.ap_args, args) with
364+
| jsx_tag :: _, _ :: rest_args -> (
365+
match extract_nested_external_component_field jsx_tag with
366+
| Some (id, dynamic_import, hidden_name) ->
367+
E.ml_var_dot ~dynamic_import id hidden_name :: rest_args
368+
| None -> args)
369+
| _ -> args
370+
else args
371+
in
303372

304373
let fn = E.ml_var_dot ~dynamic_import module_id ident_info.name in
305374
let expression =
@@ -1524,6 +1593,17 @@ let compile output_prefix =
15241593
(Ext_list.append block args_code, b :: fn_code)
15251594
| {value = None} -> assert false)
15261595
in
1596+
let args =
1597+
if appinfo.ap_transformed_jsx then
1598+
match (appinfo.ap_args, args) with
1599+
| jsx_tag :: _, _ :: rest_args -> (
1600+
match extract_nested_external_component_field jsx_tag with
1601+
| Some (id, dynamic_import, hidden_name) ->
1602+
E.ml_var_dot ~dynamic_import id hidden_name :: rest_args
1603+
| None -> args)
1604+
| _ -> args
1605+
else args
1606+
in
15271607
match (ap_func, lambda_cxt.continuation) with
15281608
| ( Lvar fn_id,
15291609
( EffectCall (Maybe_tail_is_return (Tail_with_name {label = Some ret}))
@@ -1583,6 +1663,48 @@ let compile output_prefix =
15831663
and compile_prim (prim_info : Lam.prim_info)
15841664
(lambda_cxt : Lam_compile_context.t) =
15851665
match prim_info with
1666+
| {
1667+
primitive =
1668+
Pjs_call
1669+
{
1670+
prim_name = "jsx" | "jsxs" | "jsxKeyed" | "jsxsKeyed";
1671+
transformed_jsx = true;
1672+
_;
1673+
};
1674+
args = jsx_tag :: rest_args;
1675+
loc;
1676+
} ->
1677+
let new_cxt = {lambda_cxt with continuation = NeedValue Not_tail} in
1678+
let tag_block, tag_expr =
1679+
match extract_nested_external_component_field jsx_tag with
1680+
| Some (id, dynamic_import, hidden_name) -> (
1681+
match
1682+
Lam_compile_env.query_external_id_info ~dynamic_import id
1683+
(hidden_name ^ "$jsx")
1684+
with
1685+
| exception Not_found -> (
1686+
match compile_lambda new_cxt jsx_tag with
1687+
| {block; value = Some b} -> (block, b)
1688+
| {value = None} -> assert false)
1689+
| _ -> ([], E.ml_var_dot ~dynamic_import id hidden_name))
1690+
| None -> (
1691+
match compile_lambda new_cxt jsx_tag with
1692+
| {block; value = Some b} -> (block, b)
1693+
| {value = None} -> assert false)
1694+
in
1695+
let rest_blocks, rest_exprs =
1696+
Ext_list.split_map rest_args (fun x ->
1697+
match compile_lambda new_cxt x with
1698+
| {block; value = Some b} -> (block, b)
1699+
| {value = None} -> assert false)
1700+
in
1701+
let args_code : J.block = List.concat (tag_block :: rest_blocks) in
1702+
let exp =
1703+
Lam_compile_primitive.translate output_prefix loc lambda_cxt
1704+
prim_info.primitive (tag_expr :: rest_exprs)
1705+
in
1706+
Js_output.output_of_block_and_expression lambda_cxt.continuation args_code
1707+
exp
15861708
| {
15871709
primitive = Pfield (_, fld_info);
15881710
args = [Lglobal_module (id, dynamic_import)];

compiler/core/lam_pass_remove_alias.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t =
133133
ap_func =
134134
Lprim
135135
{
136-
primitive = Pfield (_, Fld_module {name = fld_name});
136+
primitive =
137+
Pfield (_, Fld_module {name = fld_name; jsx_component = _});
137138
args = [Lglobal_module (ident, dynamic_import)];
138139
_;
139140
} as l1;

compiler/core/lam_print.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ let lambda ppf v =
323323
fprintf ppf ")@ %a)@]" lam body
324324
| Lprim
325325
{
326-
primitive = Pfield (n, Fld_module {name = s});
326+
primitive = Pfield (n, Fld_module {name = s; jsx_component = _});
327327
args = [Lglobal_module (id, dynamic_import)];
328328
_;
329329
} ->

compiler/ml/lambda.ml

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ let ref_tag_info : tag_info =
113113

114114
type field_dbg_info =
115115
| Fld_record of {name: string; mutable_flag: Asttypes.mutable_flag}
116-
| Fld_module of {name: string}
116+
| Fld_module of {name: string; jsx_component: bool}
117117
| Fld_record_inline of {name: string}
118118
| Fld_record_extension of {name: string}
119119
| Fld_tuple
@@ -134,6 +134,8 @@ let fld_record_extension (lbl : label) =
134134
Fld_record_extension
135135
{name = Ext_list.find_def lbl.lbl_attributes find_name lbl.lbl_name}
136136

137+
let fld_module ~name ~jsx_component = Fld_module {name; jsx_component}
138+
137139
let ref_field_info : field_dbg_info =
138140
Fld_record {name = "contents"; mutable_flag = Mutable}
139141

@@ -620,11 +622,28 @@ let rec transl_normal_path = function
620622
else Lvar id
621623
| Pdot (p, s, pos) ->
622624
Lprim
623-
( Pfield (pos, Fld_module {name = s}),
625+
( Pfield (pos, Fld_module {name = s; jsx_component = false}),
624626
[transl_normal_path p],
625627
Location.none )
626628
| Papply _ -> assert false
627629

630+
let transl_jsx_path path =
631+
let rec aux ~is_final = function
632+
| Path.Pident id ->
633+
if Ident.global id then Lprim (Pgetglobal id, [], Location.none)
634+
else Lvar id
635+
| Pdot (p, s, pos) ->
636+
Lprim
637+
( Pfield
638+
( pos,
639+
Fld_module
640+
{name = s; jsx_component = is_final && String.equal s "make"} ),
641+
[aux ~is_final:false p],
642+
Location.none )
643+
| Papply _ -> assert false
644+
in
645+
aux ~is_final:true path
646+
628647
(* Translation of identifiers *)
629648

630649
let transl_module_path ?(loc = Location.none) env path =
@@ -633,6 +652,9 @@ let transl_module_path ?(loc = Location.none) env path =
633652
let transl_value_path ?(loc = Location.none) env path =
634653
transl_normal_path (Env.normalize_path_prefix (Some loc) env path)
635654

655+
let transl_jsx_value_path ?(loc = Location.none) env path =
656+
transl_jsx_path (Env.normalize_path_prefix (Some loc) env path)
657+
636658
let transl_extension_path = transl_value_path
637659

638660
(* Apply a substitution to a lambda-term.

0 commit comments

Comments
 (0)