diff --git a/CHANGELOG.md b/CHANGELOG.md index e9bbc2ec47..011296205e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - Ast cleanup: explicit representation for optional record fields in types. https://github.com/rescript-lang/rescript/pull/7190 https://github.com/rescript-lang/rescript/pull/7191 - AST cleanup: first-class expression and patterns for records with optional fields. https://github.com/rescript-lang/rescript/pull/7192 - AST cleanup: Represent the arity of uncurried function definitions directly in the AST. https://github.com/rescript-lang/rescript/pull/7197 +- AST cleanup: Remove Pexp_function from the AST. https://github.com/rescript-lang/rescript/pull/7198 # 12.0.0-alpha.5 diff --git a/analysis/reanalyze/src/Arnold.ml b/analysis/reanalyze/src/Arnold.ml index 7c56cecaf8..f9598cd0dc 100644 --- a/analysis/reanalyze/src/Arnold.ml +++ b/analysis/reanalyze/src/Arnold.ml @@ -908,7 +908,7 @@ module Compile = struct let open Command in c +++ ConstrOption Rnone | _ -> c) - | Texp_function {cases} -> cases |> List.map (case ~ctx) |> Command.nondet + | Texp_function {case = case_} -> case ~ctx case_ | Texp_match (e, casesOk, casesExn, _partial) when not (casesExn diff --git a/analysis/reanalyze/src/DeadValue.ml b/analysis/reanalyze/src/DeadValue.ml index ef3ab19018..9e102cba52 100644 --- a/analysis/reanalyze/src/DeadValue.ml +++ b/analysis/reanalyze/src/DeadValue.ml @@ -156,18 +156,16 @@ let rec collectExpr super self (e : Typedtree.expression) = exp_desc = Texp_function { - cases = - [ - { - c_lhs = {pat_desc = Tpat_var (etaArg, _)}; - c_rhs = - { - exp_desc = - Texp_apply - ({exp_desc = Texp_ident (idArg2, _, _)}, args); - }; - }; - ]; + case = + { + c_lhs = {pat_desc = Tpat_var (etaArg, _)}; + c_rhs = + { + exp_desc = + Texp_apply + ({exp_desc = Texp_ident (idArg2, _, _)}, args); + }; + }; }; } ) when Ident.name idArg = "arg" diff --git a/analysis/src/DocumentSymbol.ml b/analysis/src/DocumentSymbol.ml index 44580f1e68..0e5b982b5b 100644 --- a/analysis/src/DocumentSymbol.ml +++ b/analysis/src/DocumentSymbol.ml @@ -41,7 +41,6 @@ let command ~path = let rec exprKind (exp : Parsetree.expression) = match exp.pexp_desc with | Pexp_fun _ -> Function - | Pexp_function _ -> Function | Pexp_constraint (e, _) -> exprKind e | Pexp_constant (Pconst_string _) -> String | Pexp_constant (Pconst_float _ | Pconst_integer _) -> Number diff --git a/analysis/src/Utils.ml b/analysis/src/Utils.ml index 43117e4f78..127ceef0f3 100644 --- a/analysis/src/Utils.ml +++ b/analysis/src/Utils.ml @@ -85,7 +85,6 @@ let identifyPexp pexp = | Parsetree.Pexp_ident _ -> "Pexp_ident" | Pexp_constant _ -> "Pexp_constant" | Pexp_let _ -> "Pexp_let" - | Pexp_function _ -> "Pexp_function" | Pexp_fun _ -> "Pexp_fun" | Pexp_apply _ -> "Pexp_apply" | Pexp_match _ -> "Pexp_match" diff --git a/compiler/frontend/bs_ast_mapper.ml b/compiler/frontend/bs_ast_mapper.ml index f63531e6b2..78adb57b4c 100644 --- a/compiler/frontend/bs_ast_mapper.ml +++ b/compiler/frontend/bs_ast_mapper.ml @@ -319,7 +319,6 @@ module E = struct fun_ ~loc ~attrs ~arity lab (map_opt (sub.expr sub) def) (sub.pat sub p) (sub.expr sub e) - | Pexp_function pel -> function_ ~loc ~attrs (sub.cases sub pel) | Pexp_apply (e, l) -> apply ~loc ~attrs (sub.expr sub e) (List.map (map_snd (sub.expr sub)) l) | Pexp_match (e, pel) -> diff --git a/compiler/frontend/bs_builtin_ppx.ml b/compiler/frontend/bs_builtin_ppx.ml index 5a0c31d22d..a770992366 100644 --- a/compiler/frontend/bs_builtin_ppx.ml +++ b/compiler/frontend/bs_builtin_ppx.ml @@ -110,9 +110,6 @@ let expr_mapper ~async_context ~in_function_def (self : mapper) | Pexp_constant (Pconst_integer (s, Some 'l')) -> {e with pexp_desc = Pexp_constant (Pconst_integer (s, None))} (* End rewriting *) - | Pexp_function _ -> - async_context := false; - default_expr_mapper self e | _ when Ast_uncurried.expr_is_uncurried_fun e && diff --git a/compiler/gentype/TranslateStructure.ml b/compiler/gentype/TranslateStructure.ml index 15d24f0731..8cab0461b4 100644 --- a/compiler/gentype/TranslateStructure.ml +++ b/compiler/gentype/TranslateStructure.ml @@ -3,9 +3,8 @@ open GenTypeCommon let rec addAnnotationsToTypes_ ~config ~(expr : Typedtree.expression) (arg_types : arg_type list) = match (expr.exp_desc, expr.exp_type.desc, arg_types) with - | ( Texp_function {arg_label; param; cases = [{c_rhs}]}, - _, - {a_type} :: next_types ) -> + | Texp_function {arg_label; param; case = {c_rhs}}, _, {a_type} :: next_types + -> let next_types1 = next_types |> addAnnotationsToTypes_ ~config ~expr:c_rhs in @@ -51,7 +50,7 @@ and add_annotations_to_fields ~config (expr : Typedtree.expression) (fields : fields) (arg_types : arg_type list) = match (expr.exp_desc, fields, arg_types) with | _, [], _ -> ([], arg_types |> add_annotations_to_types ~config ~expr) - | Texp_function {cases = [{c_rhs}]}, field :: next_fields, _ -> + | Texp_function {case = {c_rhs}}, field :: next_fields, _ -> let next_fields1, types1 = add_annotations_to_fields ~config c_rhs next_fields arg_types in diff --git a/compiler/ml/ast_helper.ml b/compiler/ml/ast_helper.ml index 01c5ea0e13..21bb38554f 100644 --- a/compiler/ml/ast_helper.ml +++ b/compiler/ml/ast_helper.ml @@ -152,7 +152,6 @@ module Exp = struct let let_ ?loc ?attrs a b c = mk ?loc ?attrs (Pexp_let (a, b, c)) let fun_ ?loc ?attrs ~arity a b c d = mk ?loc ?attrs (Pexp_fun (a, b, c, d, arity)) - let function_ ?loc ?attrs a = mk ?loc ?attrs (Pexp_function a) let apply ?loc ?attrs a b = mk ?loc ?attrs (Pexp_apply (a, b)) let match_ ?loc ?attrs a b = mk ?loc ?attrs (Pexp_match (a, b)) let try_ ?loc ?attrs a b = mk ?loc ?attrs (Pexp_try (a, b)) diff --git a/compiler/ml/ast_helper.mli b/compiler/ml/ast_helper.mli index cfb761485d..62ee9276a3 100644 --- a/compiler/ml/ast_helper.mli +++ b/compiler/ml/ast_helper.mli @@ -138,7 +138,6 @@ module Exp : sig pattern -> expression -> expression - val function_ : ?loc:loc -> ?attrs:attrs -> case list -> expression val apply : ?loc:loc -> ?attrs:attrs -> diff --git a/compiler/ml/ast_iterator.ml b/compiler/ml/ast_iterator.ml index 6f20cd9650..8f64d484c8 100644 --- a/compiler/ml/ast_iterator.ml +++ b/compiler/ml/ast_iterator.ml @@ -286,7 +286,6 @@ module E = struct iter_opt (sub.expr sub) def; sub.pat sub p; sub.expr sub e - | Pexp_function pel -> sub.cases sub pel | Pexp_apply (e, l) -> sub.expr sub e; List.iter (iter_snd (sub.expr sub)) l diff --git a/compiler/ml/ast_mapper.ml b/compiler/ml/ast_mapper.ml index 83fb0c0e56..383e9a47bd 100644 --- a/compiler/ml/ast_mapper.ml +++ b/compiler/ml/ast_mapper.ml @@ -282,7 +282,6 @@ module E = struct fun_ ~loc ~attrs ~arity lab (map_opt (sub.expr sub) def) (sub.pat sub p) (sub.expr sub e) - | Pexp_function pel -> function_ ~loc ~attrs (sub.cases sub pel) | Pexp_apply (e, l) -> apply ~loc ~attrs (sub.expr sub e) (List.map (map_snd (sub.expr sub)) l) | Pexp_match (e, pel) -> diff --git a/compiler/ml/ast_mapper_from0.ml b/compiler/ml/ast_mapper_from0.ml index 036ecb3755..051517062c 100644 --- a/compiler/ml/ast_mapper_from0.ml +++ b/compiler/ml/ast_mapper_from0.ml @@ -288,7 +288,7 @@ module E = struct fun_ ~loc ~attrs ~arity:None lab (map_opt (sub.expr sub) def) (sub.pat sub p) (sub.expr sub e) - | Pexp_function pel -> function_ ~loc ~attrs (sub.cases sub pel) + | Pexp_function _ -> assert false | Pexp_apply (e, l) -> apply ~loc ~attrs (sub.expr sub e) (List.map (map_snd (sub.expr sub)) l) | Pexp_match (e, pel) -> diff --git a/compiler/ml/ast_mapper_to0.ml b/compiler/ml/ast_mapper_to0.ml index 260b0de940..c45974a95d 100644 --- a/compiler/ml/ast_mapper_to0.ml +++ b/compiler/ml/ast_mapper_to0.ml @@ -287,7 +287,6 @@ module E = struct fun_ ~loc ~attrs lab (map_opt (sub.expr sub) def) (sub.pat sub p) (sub.expr sub e) - | Pexp_function pel -> function_ ~loc ~attrs (sub.cases sub pel) | Pexp_apply (e, l) -> apply ~loc ~attrs (sub.expr sub e) (List.map (map_snd (sub.expr sub)) l) | Pexp_match (e, pel) -> diff --git a/compiler/ml/depend.ml b/compiler/ml/depend.ml index a2c4e04b40..7d48262a79 100644 --- a/compiler/ml/depend.ml +++ b/compiler/ml/depend.ml @@ -221,7 +221,6 @@ let rec add_expr bv exp = | Pexp_fun (_, opte, p, e, _) -> add_opt add_expr bv opte; add_expr (add_pattern bv p) e - | Pexp_function pel -> add_cases bv pel | Pexp_apply (e, el) -> add_expr bv e; List.iter (fun (_, e) -> add_expr bv e) el diff --git a/compiler/ml/parsetree.ml b/compiler/ml/parsetree.ml index 060f9cf5b4..de6c4f0eec 100644 --- a/compiler/ml/parsetree.ml +++ b/compiler/ml/parsetree.ml @@ -224,7 +224,6 @@ and expression_desc = (* let P1 = E1 and ... and Pn = EN in E (flag = Nonrecursive) let rec P1 = E1 and ... and Pn = EN in E (flag = Recursive) *) - | Pexp_function of case list (* function P1 -> E1 | ... | Pn -> En *) | Pexp_fun of arg_label * expression option * pattern * expression * int option (* fun P -> E1 (Simple, None) diff --git a/compiler/ml/pprintast.ml b/compiler/ml/pprintast.ml index a360d3dfe6..2f3de443c7 100644 --- a/compiler/ml/pprintast.ml +++ b/compiler/ml/pprintast.ml @@ -535,7 +535,7 @@ and expression ctxt f x = pp f "((%a)@,%a)" (expression ctxt) {x with pexp_attributes=[]} (attributes ctxt) x.pexp_attributes else match x.pexp_desc with - | Pexp_function _ | Pexp_fun _ | Pexp_match _ | Pexp_try _ | Pexp_sequence _ + | Pexp_fun _ | Pexp_match _ | Pexp_try _ | Pexp_sequence _ when ctxt.pipe || ctxt.semi -> paren true (expression reset_ctxt) f x | Pexp_ifthenelse _ | Pexp_sequence _ when ctxt.ifthenelse -> @@ -551,8 +551,6 @@ and expression ctxt f x = pp f "@[<2>fun@;%s%a->@;%a@]" arity_str (label_exp ctxt) (l, e0, p) (expression ctxt) e - | Pexp_function l -> - pp f "@[function%a@]" (case_list ctxt) l | Pexp_match (e, l) -> pp f "@[@[@[<2>match %a@]@ with@]%a@]" (expression reset_ctxt) e (case_list ctxt) l diff --git a/compiler/ml/printast.ml b/compiler/ml/printast.ml index a635fc0498..385c88f4fe 100644 --- a/compiler/ml/printast.ml +++ b/compiler/ml/printast.ml @@ -233,9 +233,6 @@ and expression i ppf x = line i ppf "Pexp_let %a\n" fmt_rec_flag rf; list i value_binding ppf l; expression i ppf e - | Pexp_function l -> - line i ppf "Pexp_function\n"; - list i case ppf l | Pexp_fun (l, eo, p, e, arity) -> line i ppf "Pexp_fun\n"; let () = diff --git a/compiler/ml/printtyped.ml b/compiler/ml/printtyped.ml index 6303411246..1451266b2b 100644 --- a/compiler/ml/printtyped.ml +++ b/compiler/ml/printtyped.ml @@ -285,11 +285,11 @@ and expression i ppf x = line i ppf "Texp_let %a\n" fmt_rec_flag rf; list i value_binding ppf l; expression i ppf e - | Texp_function {arg_label = p; param; cases; partial = _} -> + | Texp_function {arg_label = p; param; case = case_; partial = _} -> line i ppf "Texp_function\n"; line i ppf "%a" Ident.print param; arg_label i ppf p; - list i case ppf cases + case i ppf case_ | Texp_apply (e, l) -> line i ppf "Texp_apply\n"; expression i ppf e; diff --git a/compiler/ml/rec_check.ml b/compiler/ml/rec_check.ml index a88b27ed7f..a669915a57 100644 --- a/compiler/ml/rec_check.ml +++ b/compiler/ml/rec_check.ml @@ -292,8 +292,8 @@ let rec expression : Env.env -> Typedtree.expression -> Use.t = let case env {Typedtree.c_rhs} = expression env c_rhs in Use.join (expression env e) (list case env cases) | Texp_override () -> assert false - | Texp_function {cases} -> - Use.delay (list (case ~scrutinee:Use.empty) env cases) + | Texp_function {case = case_} -> + Use.delay (list (case ~scrutinee:Use.empty) env [case_]) | Texp_lazy e -> ( match Typeopt.classify_lazy_argument e with | `Constant_or_function | `Identifier _ | `Float -> expression env e diff --git a/compiler/ml/tast_iterator.ml b/compiler/ml/tast_iterator.ml index ce947feb3e..b925d49336 100644 --- a/compiler/ml/tast_iterator.ml +++ b/compiler/ml/tast_iterator.ml @@ -155,7 +155,7 @@ let expr sub {exp_extra; exp_desc; exp_env; _} = | Texp_let (rec_flag, list, exp) -> sub.value_bindings sub (rec_flag, list); sub.expr sub exp - | Texp_function {cases; _} -> sub.cases sub cases + | Texp_function {case; _} -> sub.case sub case | Texp_apply (exp, list) -> sub.expr sub exp; List.iter (fun (_, o) -> Option.iter (sub.expr sub) o) list diff --git a/compiler/ml/tast_mapper.ml b/compiler/ml/tast_mapper.ml index 8d21406bd4..7a60dcf449 100644 --- a/compiler/ml/tast_mapper.ml +++ b/compiler/ml/tast_mapper.ml @@ -199,8 +199,8 @@ let expr sub x = | Texp_let (rec_flag, list, exp) -> let rec_flag, list = sub.value_bindings sub (rec_flag, list) in Texp_let (rec_flag, list, sub.expr sub exp) - | Texp_function {arg_label; param; cases; partial} -> - Texp_function {arg_label; param; cases = sub.cases sub cases; partial} + | Texp_function {arg_label; arity; param; case; partial} -> + Texp_function {arg_label; arity; param; case = sub.case sub case; partial} | Texp_apply (exp, list) -> Texp_apply (sub.expr sub exp, List.map (tuple2 id (opt (sub.expr sub))) list) diff --git a/compiler/ml/translcore.ml b/compiler/ml/translcore.ml index 1fdb458a0a..59febcda45 100644 --- a/compiler/ml/translcore.ml +++ b/compiler/ml/translcore.ml @@ -549,58 +549,54 @@ type binding = | Bind_value of value_binding list | Bind_module of Ident.t * string loc * module_expr -let rec push_defaults loc bindings cases partial = - match cases with - | [ - { - c_lhs = pat; - c_guard = None; - c_rhs = - {exp_desc = Texp_function {arg_label; param; cases; partial}} as exp; - }; - ] -> - let cases = push_defaults exp.exp_loc bindings cases partial in - [ - { - c_lhs = pat; - c_guard = None; - c_rhs = - {exp with exp_desc = Texp_function {arg_label; param; cases; partial}}; - }; - ] - | [ - { - c_lhs = pat; - c_guard = None; - c_rhs = - { - exp_attributes = [({txt = "#default"}, _)]; - exp_desc = - Texp_let (Nonrecursive, binds, ({exp_desc = Texp_function _} as e2)); - }; - }; - ] -> +let rec push_defaults loc bindings case partial = + match case with + | { + c_lhs = pat; + c_guard = None; + c_rhs = + {exp_desc = Texp_function {arg_label; arity; param; case; partial}} as exp; + } -> + let case = push_defaults exp.exp_loc bindings case partial in + + { + c_lhs = pat; + c_guard = None; + c_rhs = + { + exp with + exp_desc = Texp_function {arg_label; arity; param; case; partial}; + }; + } + | { + c_lhs = pat; + c_guard = None; + c_rhs = + { + exp_attributes = [({txt = "#default"}, _)]; + exp_desc = + Texp_let (Nonrecursive, binds, ({exp_desc = Texp_function _} as e2)); + }; + } -> push_defaults loc (Bind_value binds :: bindings) - [{c_lhs = pat; c_guard = None; c_rhs = e2}] + {c_lhs = pat; c_guard = None; c_rhs = e2} partial - | [ - { - c_lhs = pat; - c_guard = None; - c_rhs = - { - exp_attributes = [({txt = "#modulepat"}, _)]; - exp_desc = - Texp_letmodule (id, name, mexpr, ({exp_desc = Texp_function _} as e2)); - }; - }; - ] -> + | { + c_lhs = pat; + c_guard = None; + c_rhs = + { + exp_attributes = [({txt = "#modulepat"}, _)]; + exp_desc = + Texp_letmodule (id, name, mexpr, ({exp_desc = Texp_function _} as e2)); + }; + } -> push_defaults loc (Bind_module (id, name, mexpr) :: bindings) - [{c_lhs = pat; c_guard = None; c_rhs = e2}] + {c_lhs = pat; c_guard = None; c_rhs = e2} partial - | [case] -> + | case -> let exp = List.fold_left (fun exp binds -> @@ -614,45 +610,7 @@ let rec push_defaults loc bindings cases partial = }) case.c_rhs bindings in - [{case with c_rhs = exp}] - | {c_lhs = pat; c_rhs = exp; c_guard = _} :: _ when bindings <> [] -> - let param = Typecore.name_pattern "param" cases in - let name = Ident.name param in - let exp = - { - exp with - exp_loc = loc; - exp_desc = - Texp_match - ( { - exp with - exp_type = pat.pat_type; - exp_desc = - Texp_ident - ( Path.Pident param, - mknoloc (Longident.Lident name), - { - val_type = pat.pat_type; - val_kind = Val_reg; - val_attributes = []; - Types.val_loc = Location.none; - } ); - }, - cases, - [], - partial ); - } - in - push_defaults loc bindings - [ - { - c_lhs = {pat with pat_desc = Tpat_var (param, mknoloc name)}; - c_guard = None; - c_rhs = exp; - }; - ] - Total - | _ -> cases + {case with c_rhs = exp} (* Assertions *) @@ -716,7 +674,7 @@ and transl_exp0 (e : Typedtree.expression) : Lambda.lambda = | Texp_constant cst -> Lconst (Const_base cst) | Texp_let (rec_flag, pat_expr_list, body) -> transl_let rec_flag pat_expr_list (transl_exp body) - | Texp_function {arg_label = _; param; cases; partial} -> + | Texp_function {arg_label = _; param; case; partial} -> let async = has_async_attribute e in let directive = match extract_directive_for_fn e with @@ -724,7 +682,7 @@ and transl_exp0 (e : Typedtree.expression) : Lambda.lambda = | Some (directive, _) -> Some directive in let params, body, return_unit = - let pl = push_defaults e.exp_loc [] cases partial in + let pl = push_defaults e.exp_loc [] case partial in transl_function e.exp_loc partial param pl in let attr = @@ -1088,32 +1046,28 @@ and transl_apply ?(inlined = Default_inline) sargs) : Lambda.lambda) -and transl_function loc partial param cases = - match cases with - | [ - { - c_lhs = pat; - c_guard = None; - c_rhs = - { - exp_desc = - Texp_function - {arg_label = _; param = param'; cases; partial = partial'}; - } as exp; - }; - ] +and transl_function loc partial param case = + match case with + | { + c_lhs = pat; + c_guard = None; + c_rhs = + { + exp_desc = + Texp_function {arg_label = _; param = param'; case; partial = partial'}; + } as exp; + } when Parmatch.inactive ~partial pat && not (exp |> has_async_attribute) -> let params, body, return_unit = - transl_function exp.exp_loc partial' param' cases + transl_function exp.exp_loc partial' param' case in ( param :: params, Matching.for_function loc None (Lvar param) [(pat, body)] partial, return_unit ) - | {c_rhs = {exp_env; exp_type}; _} :: _ -> + | {c_rhs = {exp_env; exp_type}; _} -> ( [param], - Matching.for_function loc None (Lvar param) (transl_cases cases) partial, + Matching.for_function loc None (Lvar param) [transl_case case] partial, is_base_type exp_env exp_type Predef.path_unit ) - | _ -> assert false and transl_let rec_flag pat_expr_list body = match rec_flag with diff --git a/compiler/ml/typecore.ml b/compiler/ml/typecore.ml index fba16114be..992e64403d 100644 --- a/compiler/ml/typecore.ml +++ b/compiler/ml/typecore.ml @@ -137,7 +137,6 @@ let iter_expression f e = | Pexp_extension _ (* we don't iterate under extension point *) | Pexp_ident _ | Pexp_new _ | Pexp_constant _ -> () - | Pexp_function pel -> List.iter case pel | Pexp_fun (_, eo, _, e, _) -> may expr eo; expr e @@ -1917,8 +1916,6 @@ let rec type_approx env sexp = | Pexp_fun (p, _, _, e, _arity) -> let ty = if is_optional p then type_option (newvar ()) else newvar () in newty (Tarrow (p, ty, type_approx env e, Cok)) - | Pexp_function ({pc_rhs = e} :: _) -> - newty (Tarrow (Nolabel, newvar (), type_approx env e, Cok)) | Pexp_match (_, {pc_rhs = e} :: _) -> type_approx env e | Pexp_try (e, _) -> type_approx env e | Pexp_tuple l -> newty (Ttuple (List.map (type_approx env) l)) @@ -2374,7 +2371,7 @@ and type_expect_ ?type_clash_context ?in_function ?(recarg = Rejected) env sexp exp_attributes = sexp.pexp_attributes; exp_env = env; } - | Pexp_fun (l, Some default, spat, sbody, _arity) -> + | Pexp_fun (l, Some default, spat, sbody, arity) -> assert (is_optional l); (* default allowed only with optional argument *) let open Ast_helper in @@ -2412,14 +2409,11 @@ and type_expect_ ?type_clash_context ?in_function ?(recarg = Rejected) env sexp [Vb.mk spat smatch] sbody in - type_function ?in_function loc sexp.pexp_attributes env ty_expected l + type_function ?in_function ~arity loc sexp.pexp_attributes env ty_expected l [Exp.case pat body] - | Pexp_fun (l, None, spat, sbody, _arity) -> - type_function ?in_function loc sexp.pexp_attributes env ty_expected l + | Pexp_fun (l, None, spat, sbody, arity) -> + type_function ?in_function ~arity loc sexp.pexp_attributes env ty_expected l [Ast_helper.Exp.case spat sbody] - | Pexp_function caselist -> - type_function ?in_function loc sexp.pexp_attributes env ty_expected Nolabel - caselist | Pexp_apply (sfunct, sargs) -> assert (sargs <> []); begin_def (); @@ -3279,7 +3273,7 @@ and type_expect_ ?type_clash_context ?in_function ?(recarg = Rejected) env sexp | Pexp_extension ext -> raise (Error_forward (Builtin_attributes.error_of_extension ext)) -and type_function ?in_function loc attrs env ty_expected l caselist = +and type_function ?in_function ~arity loc attrs env ty_expected l caselist = let loc_fun, ty_fun = match in_function with | Some p -> p @@ -3312,13 +3306,14 @@ and type_function ?in_function loc attrs env ty_expected l caselist = type_cases ~in_function:(loc_fun, ty_fun) env ty_arg ty_res true loc caselist in + let case = List.hd cases in if is_optional l && not_function env ty_res then - Location.prerr_warning (List.hd cases).c_lhs.pat_loc + Location.prerr_warning case.c_lhs.pat_loc Warnings.Unerasable_optional_argument; let param = name_pattern "param" cases in re { - exp_desc = Texp_function {arg_label = l; param; cases; partial}; + exp_desc = Texp_function {arg_label = l; arity; param; case; partial}; exp_loc = loc; exp_extra = []; exp_type = instance env (newgenty (Tarrow (l, ty_arg, ty_res, Cok))); @@ -3409,119 +3404,9 @@ and type_label_exp ?type_clash_context create env loc ty_expected and type_argument ?type_clash_context ?recarg env sarg ty_expected' ty_expected = - (* ty_expected' may be generic *) - let no_labels ty = - let ls, tvar = list_labels env ty in - (not tvar) && List.for_all (fun x -> x = Nolabel) ls - in - let rec is_inferred sexp = - match sexp.pexp_desc with - | Pexp_ident _ | Pexp_apply _ | Pexp_field _ | Pexp_constraint _ - | Pexp_coerce _ | Pexp_send _ | Pexp_new _ -> - true - | Pexp_sequence (_, e) | Pexp_open (_, _, e) -> is_inferred e - | Pexp_ifthenelse (_, e1, Some e2) -> is_inferred e1 && is_inferred e2 - | _ -> false - in - match expand_head env ty_expected' with - | {desc = Tarrow (Nolabel, ty_arg, ty_res, _); level = _} - when is_inferred sarg -> - (* apply optional arguments when expected type is "" *) - (* we must be very careful about not breaking the semantics *) - let texp = type_exp env sarg in - let rec make_args args ty_fun = - match (expand_head env ty_fun).desc with - | Tarrow (l, ty_arg, ty_fun, _) when is_optional l -> - let ty = option_none (instance env ty_arg) sarg.pexp_loc in - make_args ((l, Some ty) :: args) ty_fun - | Tarrow (Nolabel, _, ty_res', _) -> - (List.rev args, ty_fun, no_labels ty_res') - | Tvar _ -> (List.rev args, ty_fun, false) - | _ -> ([], texp.exp_type, false) - in - let args, ty_fun', simple_res = make_args [] texp.exp_type in - let texp = {texp with exp_type = instance env texp.exp_type} - and ty_fun = instance env ty_fun' in - if not (simple_res || no_labels ty_res) then ( - unify_exp env texp ty_expected; - texp) - else ( - unify_exp env {texp with exp_type = ty_fun} ty_expected; - if args = [] then texp - else - (* eta-expand to avoid side effects *) - let var_pair name ty = - let id = Ident.create name in - ( { - pat_desc = Tpat_var (id, mknoloc name); - pat_type = ty; - pat_extra = []; - pat_attributes = []; - pat_loc = Location.none; - pat_env = env; - }, - { - exp_type = ty; - exp_loc = Location.none; - exp_env = env; - exp_extra = []; - exp_attributes = []; - exp_desc = - Texp_ident - ( Path.Pident id, - mknoloc (Longident.Lident name), - { - val_type = ty; - val_kind = Val_reg; - val_attributes = []; - Types.val_loc = Location.none; - } ); - } ) - in - let eta_pat, eta_var = var_pair "eta" ty_arg in - let func texp = - let e = - { - texp with - exp_type = ty_res; - exp_desc = Texp_apply (texp, args @ [(Nolabel, Some eta_var)]); - } - in - let cases = [case eta_pat e] in - let param = name_pattern "param" cases in - { - texp with - exp_type = ty_fun; - exp_desc = - Texp_function {arg_label = Nolabel; param; cases; partial = Total}; - } - in - Location.prerr_warning texp.exp_loc - (Warnings.Eliminated_optional_arguments - (List.map (fun (l, _) -> Printtyp.string_of_label l) args)); - (* let-expand to have side effects *) - let let_pat, let_var = var_pair "arg" texp.exp_type in - re - { - texp with - exp_type = ty_fun; - exp_desc = - Texp_let - ( Nonrecursive, - [ - { - vb_pat = let_pat; - vb_expr = texp; - vb_attributes = []; - vb_loc = Location.none; - }; - ], - func let_var ); - }) - | _ -> - let texp = type_expect ?type_clash_context ?recarg env sarg ty_expected' in - unify_exp ?type_clash_context env texp ty_expected; - texp + let texp = type_expect ?type_clash_context ?recarg env sarg ty_expected' in + unify_exp ?type_clash_context env texp ty_expected; + texp and is_automatic_curried_application env funct = (* When a curried function is used with uncurried application, treat it as a curried application *) diff --git a/compiler/ml/typedtree.ml b/compiler/ml/typedtree.ml index c5243bcb16..571dc3f4d6 100644 --- a/compiler/ml/typedtree.ml +++ b/compiler/ml/typedtree.ml @@ -78,8 +78,9 @@ and expression_desc = | Texp_let of rec_flag * value_binding list * expression | Texp_function of { arg_label: arg_label; + arity: int option; param: Ident.t; - cases: case list; + case: case; partial: partial; } | Texp_apply of expression * (arg_label * expression option) list diff --git a/compiler/ml/typedtree.mli b/compiler/ml/typedtree.mli index e1f6548507..a0d9844574 100644 --- a/compiler/ml/typedtree.mli +++ b/compiler/ml/typedtree.mli @@ -132,8 +132,9 @@ and expression_desc = *) | Texp_function of { arg_label: arg_label; + arity: int option; param: Ident.t; - cases: case list; + case: case; partial: partial; } (** [Pexp_fun] and [Pexp_function] both translate to [Texp_function]. diff --git a/compiler/ml/typedtreeIter.ml b/compiler/ml/typedtreeIter.ml index b4500cd6c1..858f7da4ca 100644 --- a/compiler/ml/typedtreeIter.ml +++ b/compiler/ml/typedtreeIter.ml @@ -230,7 +230,7 @@ end = struct | Texp_let (rec_flag, list, exp) -> iter_bindings rec_flag list; iter_expression exp - | Texp_function {cases; _} -> iter_cases cases + | Texp_function {case; _} -> iter_case case | Texp_apply (exp, list) -> iter_expression exp; List.iter diff --git a/compiler/syntax/src/res_ast_debugger.ml b/compiler/syntax/src/res_ast_debugger.ml index 0a6cf69a12..5b670076bc 100644 --- a/compiler/syntax/src/res_ast_debugger.ml +++ b/compiler/syntax/src/res_ast_debugger.ml @@ -558,9 +558,6 @@ module SexpAst = struct Sexp.list (map_empty ~f:value_binding vbs); expression expr; ] - | Pexp_function cases -> - Sexp.list - [Sexp.atom "Pexp_function"; Sexp.list (map_empty ~f:case cases)] | Pexp_fun (arg_lbl, expr_opt, pat, expr, _) -> Sexp.list [ diff --git a/compiler/syntax/src/res_parens.ml b/compiler/syntax/src/res_parens.ml index 10f63a1167..cb5a8b0ccc 100644 --- a/compiler/syntax/src/res_parens.ml +++ b/compiler/syntax/src/res_parens.ml @@ -51,8 +51,8 @@ let call_expr expr = | { pexp_desc = ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ - | Pexp_function _ | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ - | Pexp_try _ | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); + | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ | Pexp_try _ + | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); } -> Parenthesized | _ when Ast_uncurried.expr_is_uncurried_fun expr -> Parenthesized @@ -104,7 +104,7 @@ let unary_expr_operand expr = | { pexp_desc = ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ - | Pexp_function _ | Pexp_constraint _ | Pexp_setfield _ + | Pexp_constraint _ | Pexp_setfield _ | Pexp_extension _ (* readability? maybe remove *) | Pexp_match _ | Pexp_try _ | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); } -> @@ -132,10 +132,7 @@ let binary_expr_operand ~is_lhs expr = | {pexp_desc = Pexp_fun _} when ParsetreeViewer.is_underscore_apply_sugar expr -> Nothing - | { - pexp_desc = - Pexp_constraint _ | Pexp_fun _ | Pexp_function _ | Pexp_newtype _; - } -> + | {pexp_desc = Pexp_constraint _ | Pexp_fun _ | Pexp_newtype _} -> Parenthesized | _ when Ast_uncurried.expr_is_uncurried_fun expr -> Parenthesized | expr when ParsetreeViewer.is_binary_expression expr -> Parenthesized @@ -228,8 +225,8 @@ let lazy_or_assert_or_await_expr_rhs ?(in_await = false) expr = | { pexp_desc = ( Pexp_lazy _ | Pexp_assert _ | Pexp_fun _ | Pexp_newtype _ - | Pexp_function _ | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ - | Pexp_try _ | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); + | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ | Pexp_try _ + | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); } -> Parenthesized | _ @@ -276,9 +273,8 @@ let field_expr expr = pexp_desc = ( Pexp_lazy _ | Pexp_assert _ | Pexp_extension _ (* %extension.x vs (%extension).x *) | Pexp_fun _ - | Pexp_newtype _ | Pexp_function _ | Pexp_constraint _ | Pexp_setfield _ - | Pexp_match _ | Pexp_try _ | Pexp_while _ | Pexp_for _ - | Pexp_ifthenelse _ ); + | Pexp_newtype _ | Pexp_constraint _ | Pexp_setfield _ | Pexp_match _ + | Pexp_try _ | Pexp_while _ | Pexp_for _ | Pexp_ifthenelse _ ); } -> Parenthesized | _ when ParsetreeViewer.has_await_attribute expr.pexp_attributes -> diff --git a/compiler/syntax/src/res_printer.ml b/compiler/syntax/src/res_printer.ml index a5fde5b0ae..383848802e 100644 --- a/compiler/syntax/src/res_printer.ml +++ b/compiler/syntax/src/res_printer.ml @@ -3394,8 +3394,6 @@ and print_expression ~state (e : Parsetree.expression) cmt_tbl = Doc.space; print_cases ~state cases cmt_tbl; ] - | Pexp_function cases -> - Doc.concat [Doc.text "x => switch x "; print_cases ~state cases cmt_tbl] | Pexp_coerce (expr, (), typ) -> let doc_expr = print_expression_with_comments ~state expr cmt_tbl in let doc_typ = print_typ_expr ~state typ cmt_tbl in