diff --git a/compiler/core/j.ml b/compiler/core/j.ml index f7d67e47e4..4cf3dea76b 100644 --- a/compiler/core/j.ml +++ b/compiler/core/j.ml @@ -164,6 +164,7 @@ and expression_desc = | Null | Await of expression | Spread of expression + | Jsx_container_element of string * expression list and for_ident_expression = expression (* pure*) diff --git a/compiler/core/js_analyzer.ml b/compiler/core/js_analyzer.ml index 7d666cd486..c3d8d1d725 100644 --- a/compiler/core/js_analyzer.ml +++ b/compiler/core/js_analyzer.ml @@ -118,6 +118,7 @@ let rec no_side_effect_expression_desc (x : J.expression_desc) = | FlatCall _ | Call _ | New _ | Raw_js_code _ (* actually true? *) -> false | Await _ -> false | Spread _ -> false + | Jsx_container_element _ -> false and no_side_effect (x : J.expression) = no_side_effect_expression_desc x.expression_desc @@ -232,6 +233,7 @@ let rec eq_expression ({expression_desc = x0} : J.expression) | Caml_block_tag _ | Object _ | Tagged_template _ | Await _ -> false | Spread _ -> false + | Jsx_container_element _ -> false and eq_expression_list xs ys = Ext_list.for_all2_no_exn xs ys eq_expression diff --git a/compiler/core/js_dump.ml b/compiler/core/js_dump.ml index bc174e7dd5..994cda5ddd 100644 --- a/compiler/core/js_dump.ml +++ b/compiler/core/js_dump.ml @@ -174,6 +174,7 @@ let rec exp_need_paren ?(arrow = false) (e : J.expression) = | Tagged_template _ -> false | Optional_block (e, true) when arrow -> exp_need_paren ~arrow e | Optional_block _ -> false + | Jsx_container_element _ -> false (** Print as underscore for unused vars, may not be needed in the future *) @@ -955,6 +956,9 @@ and expression_desc cxt ~(level : int) f x : cxt = P.cond_paren_group f (level > 13) (fun _ -> P.string f "..."; expression ~level:13 cxt f e) + | Jsx_container_element (name, children) -> + P.string f (Format.sprintf "<%s>" name name); + cxt and property_name_and_value_list cxt f (l : J.property_map) = iter_lst cxt f l diff --git a/compiler/core/js_fold.ml b/compiler/core/js_fold.ml index 71109c9966..152a162301 100644 --- a/compiler/core/js_fold.ml +++ b/compiler/core/js_fold.ml @@ -187,6 +187,7 @@ class fold = | Spread _x0 -> let _self = _self#expression _x0 in _self + | Jsx_container_element _ -> _self method for_ident_expression : for_ident_expression -> 'self_type = _self#expression diff --git a/compiler/core/js_record_fold.ml b/compiler/core/js_record_fold.ml index 1756daaee6..415398894b 100644 --- a/compiler/core/js_record_fold.ml +++ b/compiler/core/js_record_fold.ml @@ -193,6 +193,9 @@ let expression_desc : 'a. ('a, expression_desc) fn = | Spread _x0 -> let st = _self.expression _self st _x0 in st + | Jsx_container_element (_x0, _x1) -> + let st = list _self.expression _self st _x1 in + st let for_ident_expression : 'a. ('a, for_ident_expression) fn = fun _self arg -> _self.expression _self arg diff --git a/compiler/core/js_record_iter.ml b/compiler/core/js_record_iter.ml index c43f41ff1b..5e31f8316b 100644 --- a/compiler/core/js_record_iter.ml +++ b/compiler/core/js_record_iter.ml @@ -144,6 +144,7 @@ let expression_desc : expression_desc fn = | Null -> () | Await _x0 -> _self.expression _self _x0 | Spread _x0 -> _self.expression _self _x0 + | Jsx_container_element (_, children) -> list _self.expression _self children let for_ident_expression : for_ident_expression fn = fun _self arg -> _self.expression _self arg diff --git a/compiler/core/js_record_map.ml b/compiler/core/js_record_map.ml index 8c63435eaa..1ade193290 100644 --- a/compiler/core/js_record_map.ml +++ b/compiler/core/js_record_map.ml @@ -191,6 +191,8 @@ let expression_desc : expression_desc fn = | Spread _x0 -> let _x0 = _self.expression _self _x0 in Spread _x0 + | Jsx_container_element (name, children) -> + Jsx_container_element (name, children) let for_ident_expression : for_ident_expression fn = fun _self arg -> _self.expression _self arg diff --git a/compiler/core/lam.ml b/compiler/core/lam.ml index 77f991e181..67c20def2b 100644 --- a/compiler/core/lam.ml +++ b/compiler/core/lam.ml @@ -102,6 +102,7 @@ module Types = struct | Lwhile of t * t | Lfor of ident * t * t * Asttypes.direction_flag * t | Lassign of ident * t + | LJsx_container_element of (* name *) string * (* children *) t list (* | Lsend of Lam_compat.meth_kind * t * t * t list * Location.t *) end @@ -149,6 +150,7 @@ module X = struct | Lwhile of t * t | Lfor of ident * t * t * Asttypes.direction_flag * t | Lassign of ident * t + | LJsx_container_element of (* name *) string * (* children *) t list (* | Lsend of Lam_compat.meth_kind * t * t * t list * Location.t *) end @@ -239,6 +241,8 @@ let inner_map (l : t) (f : t -> X.t) : X.t = | Lassign (id, e) -> let e = f e in Lassign (id, e) + | LJsx_container_element (name, children) -> + LJsx_container_element (name, List.map f children) (* | Lsend (k, met, obj, args, loc) -> let met = f met in let obj = f obj in @@ -392,6 +396,7 @@ let rec eq_approx (l1 : t) (l2 : t) = | Lletrec _ | Lswitch _ | Lstaticcatch _ | Ltrywith _ | Lfor (_, _, _, _, _) -> false + | LJsx_container_element _ -> false and eq_option l1 l2 = match l1 with @@ -444,6 +449,9 @@ let global_module ?(dynamic_import = false) id = Lglobal_module (id, dynamic_import) let const ct : t = Lconst ct +let jsx_container_element name children : t = + LJsx_container_element (name, children) + let function_ ~attr ~arity ~params ~body : t = Lfunction {arity; params; body; attr} diff --git a/compiler/core/lam.mli b/compiler/core/lam.mli index 66858ac2a4..1b3f7f1904 100644 --- a/compiler/core/lam.mli +++ b/compiler/core/lam.mli @@ -75,6 +75,7 @@ and t = private | Lwhile of t * t | Lfor of ident * t * t * Asttypes.direction_flag * t | Lassign of ident * t + | LJsx_container_element of (* name *) string * (* children *) t list (* | Lsend of Lambda.meth_kind * t * t * t list * Location.t *) (* | Levent of t * Lambda.lambda_event @@ -161,3 +162,5 @@ val for_ : ident -> t -> t -> Asttypes.direction_flag -> t -> t (**************************************************************) val eq_approx : t -> t -> bool + +val jsx_container_element : string -> t list -> t diff --git a/compiler/core/lam_analysis.ml b/compiler/core/lam_analysis.ml index 793d83b4ad..1e7e959ae3 100644 --- a/compiler/core/lam_analysis.ml +++ b/compiler/core/lam_analysis.ml @@ -128,6 +128,10 @@ let rec no_side_effects (lam : Lam.t) : bool = } -> no_side_effects arg | Lapply _ -> false + | LJsx_container_element (name, children) -> + List.fold_left + (fun acc child -> acc || no_side_effects child) + false children (* we need purity analysis .. *) (* @@ -180,6 +184,8 @@ let rec size (lam : Lam.t) = | Lwhile _ -> really_big () | Lfor _ -> really_big () | Lassign (_, v) -> 1 + size v + | LJsx_container_element (_, children) -> + Ext_list.fold_left children 1 (fun acc x -> size x + acc) (* This is side effectful, be careful *) (* | Lsend _ -> really_big () *) with Too_big_to_inline -> 1000 diff --git a/compiler/core/lam_arity_analysis.ml b/compiler/core/lam_arity_analysis.ml index 6e0027ca5f..e1f04929ec 100644 --- a/compiler/core/lam_arity_analysis.ml +++ b/compiler/core/lam_arity_analysis.ml @@ -132,6 +132,7 @@ let rec get_arity (meta : Lam_stats.t) (lam : Lam.t) : Lam_arity.t = | Lsequence (_, l2) -> get_arity meta l2 | Lstaticraise _ (* since it will not be in tail position *) -> Lam_arity.na | Lwhile _ | Lfor _ | Lassign _ -> Lam_arity.non_function_arity_info + | LJsx_container_element _ -> Lam_arity.non_function_arity_info and all_lambdas meta (xs : Lam.t list) = match xs with diff --git a/compiler/core/lam_bounded_vars.ml b/compiler/core/lam_bounded_vars.ml index 15ee9cff97..d03971d7d9 100644 --- a/compiler/core/lam_bounded_vars.ml +++ b/compiler/core/lam_bounded_vars.ml @@ -155,6 +155,8 @@ let rewrite (map : _ Hash_ident.t) (lam : Lam.t) : Lam.t = let l2 = aux l2 in Lam.while_ l1 l2 | Lassign (v, l) -> Lam.assign v (aux l) + | LJsx_container_element (tag, children) -> + Lam.jsx_container_element tag (Ext_list.map children aux) in aux lam diff --git a/compiler/core/lam_check.ml b/compiler/core/lam_check.ml index 0ef71f2cee..dd0beaa0fe 100644 --- a/compiler/core/lam_check.ml +++ b/compiler/core/lam_check.ml @@ -87,6 +87,7 @@ let check file lam = | Lifthenelse (e1, e2, e3) -> check_list [e1; e2; e3] cxt | Lsequence (e1, e2) -> check_list [e1; e2] cxt | Lassign (_id, e) -> check_staticfails e cxt + | LJsx_container_element (_tag, children) -> check_list children cxt in let rec iter_list xs = Ext_list.iter xs iter and iter_list_snd : 'a. ('a * Lam.t) list -> unit = @@ -149,6 +150,7 @@ let check file lam = | Lassign (id, e) -> use id; iter e + | LJsx_container_element (_tag, children) -> iter_list children in check_staticfails lam Set_int.empty; iter lam; diff --git a/compiler/core/lam_closure.ml b/compiler/core/lam_closure.ml index c02f05b705..a786ab4563 100644 --- a/compiler/core/lam_closure.ml +++ b/compiler/core/lam_closure.ml @@ -137,6 +137,8 @@ let free_variables (export_idents : Set_ident.t) (params : stats Map_ident.t) | Lassign (id, e) -> used top id; iter top e + | LJsx_container_element (_, children) -> + List.iter (fun child -> iter sink_pos child) children in iter Lam_var_stats.fresh_env lam; !fv diff --git a/compiler/core/lam_compile.ml b/compiler/core/lam_compile.ml index ea865bbe6f..421da7d384 100644 --- a/compiler/core/lam_compile.ml +++ b/compiler/core/lam_compile.ml @@ -1822,6 +1822,16 @@ let compile output_prefix = | Ltrywith (lam, id, catch) -> (* generate documentation *) compile_trywith lam id catch lambda_cxt + | LJsx_container_element (name, children) -> + Js_output.make [] + ~value: + { + expression_desc = + Jsx_container_element + (* Not sure how to proceed here *) + (name, []); + comment = None; + } in (compile_recursive_lets, compile_lambda) diff --git a/compiler/core/lam_convert.ml b/compiler/core/lam_convert.ml index 3f252011ef..6773dde26c 100644 --- a/compiler/core/lam_convert.ml +++ b/compiler/core/lam_convert.ml @@ -108,6 +108,7 @@ let exception_id_destructed (l : Lam.t) (fv : Ident.t) : bool = | Lifthenelse (e1, e2, e3) -> hit e1 || hit e2 || hit e3 | Lsequence (e1, e2) -> hit e1 || hit e2 | Lwhile (e1, e2) -> hit e1 || hit e2 + | LJsx_container_element (_, children) -> hit_list children in hit l @@ -506,6 +507,8 @@ let convert (exports : Set_ident.t) (lam : Lambda.lambda) : | Lfor (id, from_, to_, dir, loop) -> Lam.for_ id (convert_aux from_) (convert_aux to_) dir (convert_aux loop) | Lassign (id, body) -> Lam.assign id (convert_aux body) + | LJsx_container_element (name, children) -> + Lam.jsx_container_element name (List.map convert_aux children) and convert_let (kind : Lam_compat.let_kind) id (e : Lambda.lambda) body : Lam.t = match (kind, e) with diff --git a/compiler/core/lam_exit_count.ml b/compiler/core/lam_exit_count.ml index d9535ac2ee..20a818b9fb 100644 --- a/compiler/core/lam_exit_count.ml +++ b/compiler/core/lam_exit_count.ml @@ -97,6 +97,7 @@ let count_helper (lam : Lam.t) : collection = count l2; count l3 | Lassign (_, l) -> count l + | LJsx_container_element (_, children) -> List.iter count children and count_default sw = match sw.sw_failaction with | None -> () diff --git a/compiler/core/lam_free_variables.ml b/compiler/core/lam_free_variables.ml index 1fdd31f1c6..b8cedf2637 100644 --- a/compiler/core/lam_free_variables.ml +++ b/compiler/core/lam_free_variables.ml @@ -86,6 +86,7 @@ let pass_free_variables (l : Lam.t) : Set_ident.t = | Lwhile (e1, e2) -> free e1; free e2 + | LJsx_container_element (_, children) -> free_list children in free l; !fv diff --git a/compiler/core/lam_hit.ml b/compiler/core/lam_hit.ml index dd1c2c9270..dc0864632e 100644 --- a/compiler/core/lam_hit.ml +++ b/compiler/core/lam_hit.ml @@ -56,6 +56,7 @@ let hit_variables (fv : Set_ident.t) (l : t) : bool = | Lifthenelse (e1, e2, e3) -> hit e1 || hit e2 || hit e3 | Lsequence (e1, e2) -> hit e1 || hit e2 | Lwhile (e1, e2) -> hit e1 || hit e2 + | LJsx_container_element (_, children) -> hit_list children in hit l @@ -91,5 +92,6 @@ let hit_variable (fv : Ident.t) (l : t) : bool = | Lifthenelse (e1, e2, e3) -> hit e1 || hit e2 || hit e3 | Lsequence (e1, e2) -> hit e1 || hit e2 | Lwhile (e1, e2) -> hit e1 || hit e2 + | LJsx_container_element (_, children) -> hit_list children in hit l diff --git a/compiler/core/lam_iter.ml b/compiler/core/lam_iter.ml index 94b8729eca..ad2ada5540 100644 --- a/compiler/core/lam_iter.ml +++ b/compiler/core/lam_iter.ml @@ -80,6 +80,7 @@ let inner_iter (l : t) (f : t -> unit) : unit = f e2; f e3 | Lassign (_id, e) -> f e + | LJsx_container_element (name, children) -> List.iter f children let inner_exists (l : t) (f : t -> bool) : bool = match l with @@ -113,3 +114,4 @@ let inner_exists (l : t) (f : t -> bool) : bool = | Lwhile (e1, e2) -> f e1 || f e2 | Lfor (_v, e1, e2, _dir, e3) -> f e1 || f e2 || f e3 | Lassign (_id, e) -> f e + | LJsx_container_element (name, children) -> Ext_list.exists children f diff --git a/compiler/core/lam_pass_alpha_conversion.ml b/compiler/core/lam_pass_alpha_conversion.ml index 3beadbeb0e..5032379a5d 100644 --- a/compiler/core/lam_pass_alpha_conversion.ml +++ b/compiler/core/lam_pass_alpha_conversion.ml @@ -119,6 +119,8 @@ let alpha_conversion (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = (* Lalias-bound variables are never assigned, so don't increase v's refsimpl *) Lam.assign v (simpl l) + | LJsx_container_element (name, children) -> + Lam.jsx_container_element name (Ext_list.map children simpl) in simpl lam diff --git a/compiler/core/lam_pass_collect.ml b/compiler/core/lam_pass_collect.ml index 5f4a0d46e5..a3f70fffde 100644 --- a/compiler/core/lam_pass_collect.ml +++ b/compiler/core/lam_pass_collect.ml @@ -157,5 +157,6 @@ let collect_info (meta : Lam_stats.t) (lam : Lam.t) = (* Lalias-bound variables are never assigned, so don't increase v's refcollect *) collect l + | LJsx_container_element (_, children) -> List.iter collect children in collect lam diff --git a/compiler/core/lam_pass_count.ml b/compiler/core/lam_pass_count.ml index 3fc3a89090..0590e3a8d0 100644 --- a/compiler/core/lam_pass_count.ml +++ b/compiler/core/lam_pass_count.ml @@ -186,6 +186,7 @@ let collect_occurs lam : occ_tbl = | Lsequence (l1, l2) -> count bv l1; count bv l2 + | LJsx_container_element (_, children) -> List.iter (count bv) children and count_default bv sw = match sw.sw_failaction with | None -> () diff --git a/compiler/core/lam_pass_deep_flatten.ml b/compiler/core/lam_pass_deep_flatten.ml index c55aeec841..114180de5e 100644 --- a/compiler/core/lam_pass_deep_flatten.ml +++ b/compiler/core/lam_pass_deep_flatten.ml @@ -266,5 +266,7 @@ let deep_flatten (lam : Lam.t) : Lam.t = (* Lalias-bound variables are never assigned, so don't increase v's refaux *) Lam.assign v (aux l) + | LJsx_container_element (name, children) -> + Lam.jsx_container_element name (Ext_list.map children aux) in aux lam diff --git a/compiler/core/lam_pass_eliminate_ref.ml b/compiler/core/lam_pass_eliminate_ref.ml index 4a251c1877..f21116a7ef 100644 --- a/compiler/core/lam_pass_eliminate_ref.ml +++ b/compiler/core/lam_pass_eliminate_ref.ml @@ -98,3 +98,5 @@ let rec eliminate_ref id (lam : Lam.t) = Lam.for_ v (eliminate_ref id e1) (eliminate_ref id e2) dir (eliminate_ref id e3) | Lassign (v, e) -> Lam.assign v (eliminate_ref id e) + | LJsx_container_element (tag, children) -> + Lam.jsx_container_element tag (Ext_list.map children (eliminate_ref id)) diff --git a/compiler/core/lam_pass_exits.ml b/compiler/core/lam_pass_exits.ml index ceba4af6e5..2eb4d8b077 100644 --- a/compiler/core/lam_pass_exits.ml +++ b/compiler/core/lam_pass_exits.ml @@ -56,6 +56,7 @@ and no_bounded_variables (l : Lam.t) = | Ltrywith _ -> false | Llet _ -> false | Lletrec (decl, body) -> decl = [] && no_bounded_variables body + | LJsx_container_element _ -> false (* TODO: @@ -233,6 +234,8 @@ let subst_helper (subst : subst_tbl) (query : int -> int) (lam : Lam.t) : Lam.t | Lfor (v, l1, l2, dir, l3) -> Lam.for_ v (simplif l1) (simplif l2) dir (simplif l3) | Lassign (v, l) -> Lam.assign v (simplif l) + | LJsx_container_element (name, children) -> + Lam.jsx_container_element name (List.map simplif children) in simplif lam diff --git a/compiler/core/lam_pass_lets_dce.ml b/compiler/core/lam_pass_lets_dce.ml index ca6e32bc7c..d49dee3ea9 100644 --- a/compiler/core/lam_pass_lets_dce.ml +++ b/compiler/core/lam_pass_lets_dce.ml @@ -201,6 +201,8 @@ let lets_helper (count_var : Ident.t -> Lam_pass_count.used_info) lam : Lam.t = | Lfor (v, l1, l2, dir, l3) -> Lam.for_ v (simplif l1) (simplif l2) dir (simplif l3) | Lassign (v, l) -> Lam.assign v (simplif l) + | LJsx_container_element (name, children) -> + Lam.jsx_container_element name (Ext_list.map children simplif) in simplif lam diff --git a/compiler/core/lam_pass_remove_alias.ml b/compiler/core/lam_pass_remove_alias.ml index 065ea65edf..9927e535c9 100644 --- a/compiler/core/lam_pass_remove_alias.ml +++ b/compiler/core/lam_pass_remove_alias.ml @@ -265,5 +265,7 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t = (* Lalias-bound variables are never assigned, so don't increase v's refsimpl *) Lam.assign v (simpl l) + | LJsx_container_element (name, children) -> + Lam.jsx_container_element name (Ext_list.map children simpl) in simpl lam diff --git a/compiler/core/lam_print.ml b/compiler/core/lam_print.ml index d82956cc93..d2e220806a 100644 --- a/compiler/core/lam_print.ml +++ b/compiler/core/lam_print.ml @@ -410,6 +410,7 @@ let lambda ppf v = lam hi lam body | Lassign (id, expr) -> fprintf ppf "@[<2>(assign@ %a@ %a)@]" Ident.print id lam expr + | LJsx_container_element _ -> fprintf ppf "todo" and sequence ppf = function | Lsequence (l1, l2) -> fprintf ppf "%a@ %a" sequence l1 sequence l2 | l -> lam ppf l diff --git a/compiler/core/lam_scc.ml b/compiler/core/lam_scc.ml index 556feed559..9af63b2067 100644 --- a/compiler/core/lam_scc.ml +++ b/compiler/core/lam_scc.ml @@ -61,6 +61,7 @@ let hit_mask (mask : Hash_set_ident_mask.t) (l : Lam.t) : bool = | Lifthenelse (e1, e2, e3) -> hit e1 || hit e2 || hit e3 | Lsequence (e1, e2) -> hit e1 || hit e2 | Lwhile (e1, e2) -> hit e1 || hit e2 + | LJsx_container_element (_, children) -> hit_list children in hit l diff --git a/compiler/core/lam_subst.ml b/compiler/core/lam_subst.ml index d5469619a3..0166ea51c7 100644 --- a/compiler/core/lam_subst.ml +++ b/compiler/core/lam_subst.ml @@ -67,6 +67,8 @@ let subst (s : Lam.t Map_ident.t) lam = | Lfor (v, e1, e2, dir, e3) -> Lam.for_ v (subst_aux e1) (subst_aux e2) dir (subst_aux e3) | Lassign (id, e) -> Lam.assign id (subst_aux e) + | LJsx_container_element (tag, children) -> + Lam.jsx_container_element tag (Ext_list.map children subst_aux) and subst_decl (id, exp) = (id, subst_aux exp) and subst_case (key, case) = (key, subst_aux case) and subst_strcase (key, case) = (key, subst_aux case) diff --git a/compiler/ml/lambda.ml b/compiler/ml/lambda.ml index 26aa8a8c74..672c8e492a 100644 --- a/compiler/ml/lambda.ml +++ b/compiler/ml/lambda.ml @@ -370,6 +370,7 @@ type lambda = | Lfor of Ident.t * lambda * lambda * Asttypes.direction_flag * lambda | Lassign of Ident.t * lambda | Lsend of string * lambda * Location.t + | LJsx_container_element of (* name *) string * (* children *) lambda list and lfunction = { params: Ident.t list; @@ -479,6 +480,8 @@ let make_key e = | Lassign (x, e) -> Lassign (x, tr_rec env e) | Lsend (m, e1, _loc) -> Lsend (m, tr_rec env e1, Location.none) | Lletrec _ | Lfunction _ | Lfor _ | Lwhile _ -> raise_notrace Not_simple + | LJsx_container_element (name, children) -> + LJsx_container_element (name, List.map (tr_rec env) children) and tr_recs env es = List.map (tr_rec env) es and tr_sw env sw = { @@ -552,6 +555,7 @@ let iter f = function f e3 | Lassign (_, e) -> f e | Lsend (_k, obj, _) -> f obj + | LJsx_container_element (_name, children) -> List.iter f children module IdentSet = Set.Make (Ident) @@ -574,6 +578,7 @@ let free_ids get l = | Lvar _ | Lconst _ | Lapply _ | Lprim _ | Lswitch _ | Lstringswitch _ | Lstaticraise _ | Lifthenelse _ | Lsequence _ | Lwhile _ | Lsend _ -> () + | LJsx_container_element (_name, children) -> List.iter free children in free l; !fv @@ -680,6 +685,8 @@ let subst_lambda s lam = | Lfor (v, e1, e2, dir, e3) -> Lfor (v, subst e1, subst e2, dir, subst e3) | Lassign (id, e) -> Lassign (id, subst e) | Lsend (k, obj, loc) -> Lsend (k, subst obj, loc) + | LJsx_container_element (name, children) -> + LJsx_container_element (name, List.map subst children) and subst_decl (id, exp) = (id, subst exp) and subst_case (key, case) = (key, subst case) and subst_strcase (key, case) = (key, subst case) diff --git a/compiler/ml/lambda.mli b/compiler/ml/lambda.mli index 9e1c9b9d7c..d70dd6b5f7 100644 --- a/compiler/ml/lambda.mli +++ b/compiler/ml/lambda.mli @@ -339,6 +339,7 @@ type lambda = | Lfor of Ident.t * lambda * lambda * direction_flag * lambda | Lassign of Ident.t * lambda | Lsend of string * lambda * Location.t + | LJsx_container_element of (* name *) string * (* children *) lambda list and lfunction = { params: Ident.t list; diff --git a/compiler/ml/printlambda.ml b/compiler/ml/printlambda.ml index f0ad4698bb..17ab9f877a 100644 --- a/compiler/ml/printlambda.ml +++ b/compiler/ml/printlambda.ml @@ -388,6 +388,8 @@ let rec lam ppf = function | Lassign (id, expr) -> fprintf ppf "@[<2>(assign@ %a@ %a)@]" Ident.print id lam expr | Lsend (name, obj, _) -> fprintf ppf "@[<2>(send%s@ %a@ )@]" name lam obj + | LJsx_container_element (tag, _) -> + fprintf ppf "LJsx_container_element %s" tag and sequence ppf = function | Lsequence (l1, l2) -> fprintf ppf "%a@ %a" sequence l1 sequence l2 diff --git a/compiler/ml/printtyped.ml b/compiler/ml/printtyped.ml index 6bdd794d97..aa5fdd3123 100644 --- a/compiler/ml/printtyped.ml +++ b/compiler/ml/printtyped.ml @@ -375,6 +375,7 @@ and expression i ppf x = module_expr i ppf me | Texp_extension_constructor (li, _) -> line i ppf "Texp_extension_constructor %a" fmt_longident li + | Texp_jsx_container_element _ -> line i ppf "Texp_jsx_container_element\n" and value_description i ppf x = line i ppf "value_description %a %a\n" fmt_ident x.val_id fmt_location diff --git a/compiler/ml/rec_check.ml b/compiler/ml/rec_check.ml index 43f13b4e2c..2d089b5f08 100644 --- a/compiler/ml/rec_check.ml +++ b/compiler/ml/rec_check.ml @@ -205,6 +205,7 @@ let rec classify_expression : Typedtree.expression -> sd = | Texp_apply _ | Texp_match _ | Texp_ifthenelse _ | Texp_send _ | Texp_field _ | Texp_assert _ | Texp_try _ -> Dynamic + | Texp_jsx_container_element _ -> Static let rec expression : Env.env -> Typedtree.expression -> Use.t = fun env exp -> @@ -296,6 +297,8 @@ let rec expression : Env.env -> Typedtree.expression -> Use.t = | `Constant_or_function | `Identifier _ | `Float -> expression env e | `Other -> Use.delay (expression env e)) | Texp_extension_constructor _ -> Use.empty + | Texp_jsx_container_element (_, children) -> + Use.(join (list expression env children) Use.empty) and option : 'a. (Env.env -> 'a -> Use.t) -> Env.env -> 'a option -> Use.t = fun f env -> value_default (f env) ~default:Use.empty diff --git a/compiler/ml/tast_iterator.ml b/compiler/ml/tast_iterator.ml index 3220aa87fe..6733755efa 100644 --- a/compiler/ml/tast_iterator.ml +++ b/compiler/ml/tast_iterator.ml @@ -205,6 +205,7 @@ let expr sub {exp_extra; exp_desc; exp_env; _} = | Texp_lazy exp -> sub.expr sub exp | Texp_pack mexpr -> sub.module_expr sub mexpr | Texp_extension_constructor _ -> () + | Texp_jsx_container_element _ -> () let package_type sub {pack_fields; _} = List.iter (fun (_, p) -> sub.typ sub p) pack_fields diff --git a/compiler/ml/tast_mapper.ml b/compiler/ml/tast_mapper.ml index 8064d65990..470328a1b0 100644 --- a/compiler/ml/tast_mapper.ml +++ b/compiler/ml/tast_mapper.ml @@ -253,6 +253,8 @@ let expr sub x = | Texp_lazy exp -> Texp_lazy (sub.expr sub exp) | Texp_pack mexpr -> Texp_pack (sub.module_expr sub mexpr) | Texp_extension_constructor _ as e -> e + | Texp_jsx_container_element (name, children) -> + Texp_jsx_container_element (name, List.map (sub.expr sub) children) in {x with exp_extra; exp_desc; exp_env} diff --git a/compiler/ml/translcore.ml b/compiler/ml/translcore.ml index 4cdeb34aa5..62eface11b 100644 --- a/compiler/ml/translcore.ml +++ b/compiler/ml/translcore.ml @@ -923,6 +923,8 @@ and transl_exp0 (e : Typedtree.expression) : Lambda.lambda = optimize the translation just as Lazy.lazy_from_val would do *) Lprim (Pmakeblock Blk_lazy_general, [transl_exp e], e.exp_loc) + | Texp_jsx_container_element (name, children) -> + LJsx_container_element (name, transl_list children) and transl_list expr_list = List.map transl_exp expr_list diff --git a/compiler/ml/typecore.ml b/compiler/ml/typecore.ml index d1e593607f..636fb0b47e 100644 --- a/compiler/ml/typecore.ml +++ b/compiler/ml/typecore.ml @@ -3199,6 +3199,45 @@ and type_expect_ ?type_clash_context ?in_function ?(recarg = Rejected) env sexp | Pexp_extension ext -> raise (Error_forward (Builtin_attributes.error_of_extension ext)) | Pexp_await _ -> (* should be handled earlier *) assert false + | Pexp_jsx_element + (Jsx_container_element + { + jsx_container_element_tag_name_start = tag_name; + jsx_container_element_props = props; + }) -> + let fields = + props + |> List.filter_map (function + | JSXPropValue (name, _, value) -> + Some + ( { + txt = Longident.Ldot (Longident.Lident "JsxDOM", name.txt); + loc = name.loc; + }, + value, + false ) + | _ -> None) + in + let record = Ast_helper.Exp.record fields None in + let domProps = + Path.Pdot (Path.Pident (Ident.create "JsxDOM"), "domProps", 0) + in + let jsx_dom_type_expected = Ctype.newconstr domProps [] in + let element_type = + let path = Path.Pdot (Path.Pident (Ident.create "Jsx"), "element", 0) in + Ctype.newconstr path [] + in + let _typed_record = type_expect_ env record jsx_dom_type_expected in + { + exp_desc = + Texp_jsx_container_element + (tag_name.txt |> Longident.flatten |> String.concat ".", []); + exp_loc = loc; + exp_extra = []; + exp_type = element_type; + exp_attributes = sexp.pexp_attributes; + exp_env = env; + } | Pexp_jsx_element _ -> failwith "Pexp_jsx_element is expected to be transformed at this point" diff --git a/compiler/ml/typedtree.ml b/compiler/ml/typedtree.ml index 626950caec..4da5d069bd 100644 --- a/compiler/ml/typedtree.ml +++ b/compiler/ml/typedtree.ml @@ -124,6 +124,8 @@ and expression_desc = | Texp_lazy of expression | Texp_pack of module_expr | Texp_extension_constructor of Longident.t loc * Path.t + | Texp_jsx_container_element of + (* name *) string * (* children *) expression list and meth = Tmeth_name of string diff --git a/compiler/ml/typedtree.mli b/compiler/ml/typedtree.mli index 96da873af0..8abaf6d297 100644 --- a/compiler/ml/typedtree.mli +++ b/compiler/ml/typedtree.mli @@ -225,6 +225,8 @@ and expression_desc = | Texp_lazy of expression | Texp_pack of module_expr | Texp_extension_constructor of Longident.t loc * Path.t + | Texp_jsx_container_element of + (* name *) string * (* children *) expression list and meth = Tmeth_name of string diff --git a/compiler/ml/typedtreeIter.ml b/compiler/ml/typedtreeIter.ml index e0fe1e228e..18e1bf06f5 100644 --- a/compiler/ml/typedtreeIter.ml +++ b/compiler/ml/typedtreeIter.ml @@ -293,7 +293,10 @@ end = struct | Texp_assert exp -> iter_expression exp | Texp_lazy exp -> iter_expression exp | Texp_pack mexpr -> iter_module_expr mexpr - | Texp_extension_constructor _ -> ()); + | Texp_extension_constructor _ -> () + | Texp_jsx_container_element (_, children) -> + List.iter iter_expression children); + Iter.leave_expression exp and iter_package_type pack =