Skip to content

Commit fd1a69d

Browse files
committed
Implement typed Option stdlib optimizations
1 parent f1692ff commit fd1a69d

19 files changed

+302
-198
lines changed

compiler/frontend/ast_option_optimizations.ml

Lines changed: 0 additions & 126 deletions
This file was deleted.

compiler/frontend/ast_option_optimizations.mli

Lines changed: 0 additions & 1 deletion
This file was deleted.

compiler/frontend/bs_builtin_ppx.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ let expr_mapper ~async_context ~in_function_def (self : mapper)
112112
body;
113113
pexp_attributes;
114114
})
115-
| Pexp_apply _ ->
116-
Ast_exp_apply.app_exp_mapper e self |> Ast_option_optimizations.transform
115+
| Pexp_apply _ -> Ast_exp_apply.app_exp_mapper e self
117116
| Pexp_match
118117
( b,
119118
[

compiler/ml/printtyped.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,16 @@ and expression_extra i ppf x attrs =
260260
| Texp_newtype s ->
261261
line i ppf "Texp_newtype \"%s\"\n" s;
262262
attributes i ppf attrs
263+
| Texp_stdlib_option_call {call_kind; payload_not_nested; _} ->
264+
let kind =
265+
match call_kind with
266+
| Stdlib_option_forEach -> "forEach"
267+
| Stdlib_option_map {result_cannot_contain_undefined = _} -> "map"
268+
| Stdlib_option_flatMap -> "flatMap"
269+
in
270+
line i ppf "Texp_stdlib_option_call %s payload_not_nested=%b\n" kind
271+
payload_not_nested;
272+
attributes i ppf attrs
263273

264274
and expression i ppf x =
265275
line i ppf "expression %a\n" fmt_location x.exp_loc;

compiler/ml/tast_iterator.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,16 @@ let pat sub {pat_extra; pat_desc; pat_env; _} =
137137
| Tpat_alias (p, _, _) -> sub.pat sub p
138138

139139
let expr sub {exp_extra; exp_desc; exp_env; _} =
140-
let extra = function
140+
let rec extra = function
141141
| Texp_constraint cty -> sub.typ sub cty
142142
| Texp_coerce cty2 -> sub.typ sub cty2
143143
| Texp_newtype _ -> ()
144144
| Texp_open (_, _, _, _) -> ()
145+
| Texp_stdlib_option_call info -> stdlib_option_call info
146+
and stdlib_option_call {callback; _} = stdlib_option_callback callback
147+
and stdlib_option_callback = function
148+
| Stdlib_option_inline_lambda {body; _} -> sub.expr sub body
149+
| Stdlib_option_inline_ident expr -> sub.expr sub expr
145150
in
146151
List.iter (fun (e, _, _) -> extra e) exp_extra;
147152
sub.env sub exp_env;

compiler/ml/tast_mapper.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,27 @@ let pat sub x =
180180
{x with pat_extra; pat_desc; pat_env}
181181

182182
let expr sub x =
183+
let map_stdlib_option_callback sub = function
184+
| Stdlib_option_inline_lambda {param; body} ->
185+
Stdlib_option_inline_lambda {param; body = sub.expr sub body}
186+
| Stdlib_option_inline_ident expr ->
187+
Stdlib_option_inline_ident (sub.expr sub expr)
188+
in
189+
let map_stdlib_option_call sub {callback; call_kind; payload_not_nested} =
190+
{
191+
callback = map_stdlib_option_callback sub callback;
192+
call_kind;
193+
payload_not_nested;
194+
}
195+
in
183196
let extra = function
184197
| Texp_constraint cty -> Texp_constraint (sub.typ sub cty)
185198
| Texp_coerce cty2 -> Texp_coerce (sub.typ sub cty2)
186199
| Texp_open (ovf, path, loc, env) ->
187200
Texp_open (ovf, path, loc, sub.env sub env)
188201
| Texp_newtype _ as d -> d
202+
| Texp_stdlib_option_call info ->
203+
Texp_stdlib_option_call (map_stdlib_option_call sub info)
189204
in
190205
let exp_extra = List.map (tuple3 extra id id) x.exp_extra in
191206
let exp_env = sub.env sub x.exp_env in

compiler/ml/translcore.ml

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,16 @@ let rec cut n l =
646646

647647
let try_ids = Hashtbl.create 8
648648

649+
let stdlib_option_call_extra exp =
650+
let rec aux = function
651+
| [] -> None
652+
| (Texp_stdlib_option_call info, _, _) :: _ -> Some info
653+
| _ :: rest -> aux rest
654+
in
655+
aux exp.exp_extra
656+
657+
let lambda_none = Lconst (Const_pointer (0, Pt_shape_none))
658+
649659
let extract_directive_for_fn exp =
650660
exp.exp_attributes
651661
|> List.find_map (fun ({txt}, payload) ->
@@ -755,10 +765,11 @@ and transl_exp0 (e : Typedtree.expression) : Lambda.lambda =
755765
(Lprim
756766
(Pccall (set_transformed_jsx d ~transformed_jsx), argl, e.exp_loc))
757767
| _ -> wrap (Lprim (prim, argl, e.exp_loc))))
758-
| Texp_apply {funct; args = oargs; partial; transformed_jsx} ->
768+
| Texp_apply {funct; args = oargs; partial; transformed_jsx} -> (
759769
let inlined, funct =
760770
Translattribute.get_and_remove_inlined_attribute funct
761771
in
772+
let option_call_info = stdlib_option_call_extra e in
762773
let uncurried_partial_application =
763774
(* In case of partial application foo(args, ...) when some args are missing,
764775
get the arity *)
@@ -771,8 +782,17 @@ and transl_exp0 (e : Typedtree.expression) : Lambda.lambda =
771782
| None -> None
772783
else None
773784
in
774-
transl_apply ~inlined ~uncurried_partial_application ~transformed_jsx
775-
(transl_exp funct) oargs e.exp_loc
785+
match option_call_info with
786+
| Some info when not partial -> (
787+
match oargs with
788+
| (Nolabel, Some opt_expr) :: _ ->
789+
transl_stdlib_option_call e opt_expr info oargs
790+
| _ ->
791+
transl_apply ~inlined ~uncurried_partial_application ~transformed_jsx
792+
(transl_exp funct) oargs e.exp_loc)
793+
| _ ->
794+
transl_apply ~inlined ~uncurried_partial_application ~transformed_jsx
795+
(transl_exp funct) oargs e.exp_loc)
776796
| Texp_match (arg, pat_expr_list, exn_pat_expr_list, partial) ->
777797
transl_match e arg pat_expr_list exn_pat_expr_list partial
778798
| Texp_try (body, pat_expr_list) ->
@@ -924,6 +944,60 @@ and transl_exp0 (e : Typedtree.expression) : Lambda.lambda =
924944
if !Clflags.noassert then lambda_unit
925945
else Lifthenelse (transl_exp cond, lambda_unit, assert_failed e)
926946

947+
and bind_option_value ~payload_not_nested opt_var opt_loc callback =
948+
let value_expr =
949+
if payload_not_nested then
950+
Lprim (Pval_from_option_not_nest, [opt_var], opt_loc)
951+
else Lprim (Pval_from_option, [opt_var], opt_loc)
952+
in
953+
match callback with
954+
| Stdlib_option_inline_lambda {param; body} ->
955+
bind Strict param value_expr (transl_exp body)
956+
| Stdlib_option_inline_ident expr ->
957+
let func = transl_exp expr in
958+
let value_id = Ident.create "__res_option_value" in
959+
let apply =
960+
Lapply
961+
{
962+
ap_func = func;
963+
ap_args = [Lvar value_id];
964+
ap_inlined = Default_inline;
965+
ap_loc = expr.exp_loc;
966+
ap_transformed_jsx = false;
967+
}
968+
in
969+
bind Strict value_id value_expr apply
970+
971+
and transl_stdlib_option_call exp opt_expr info oargs =
972+
match oargs with
973+
| (Nolabel, Some _) :: (Nolabel, Some _) :: _ | (Nolabel, Some _) :: [] ->
974+
let opt_lam = transl_exp opt_expr in
975+
let opt_id = Ident.create "__res_option_opt" in
976+
let opt_var = Lvar opt_id in
977+
let callback_result =
978+
bind_option_value ~payload_not_nested:info.payload_not_nested opt_var
979+
exp.exp_loc info.callback
980+
in
981+
let some_branch =
982+
match info.call_kind with
983+
| Stdlib_option_forEach -> callback_result
984+
| Stdlib_option_map {result_cannot_contain_undefined} ->
985+
let tag =
986+
if result_cannot_contain_undefined then Blk_some_not_nested
987+
else Blk_some
988+
in
989+
Lprim (Pmakeblock tag, [callback_result], exp.exp_loc)
990+
| Stdlib_option_flatMap -> callback_result
991+
in
992+
let none_branch =
993+
match info.call_kind with
994+
| Stdlib_option_forEach -> lambda_unit
995+
| Stdlib_option_map _ | Stdlib_option_flatMap -> lambda_none
996+
in
997+
let cond = Lprim (Pis_not_none, [opt_var], exp.exp_loc) in
998+
bind Strict opt_id opt_lam (Lifthenelse (cond, some_branch, none_branch))
999+
| _ -> assert false
1000+
9271001
and transl_list expr_list = List.map transl_exp expr_list
9281002

9291003
and transl_guard guard rhs =

0 commit comments

Comments
 (0)