Skip to content

Commit 55d44fd

Browse files
cristianocclaude
andcommitted
Route Lambda.apply's eta reduction through the folding constructors
lambda.mli says a term is built through the constructors, seven of which normalize as they build. apply did not: its eta reduction substituted the call's arguments into the inner primitive and then rebuilt the result with a raw Lprim, so a primitive applied to constants was left unfolded. ((a, b) => a + b)(1, 2) left translation as (+ 1 2) rather than 3. It could only do this by owning the type; the reason it did was position, which the preceding commit fixed. Generated JavaScript is unchanged: the optimizer passes were folding this on their way past, so the same code comes out. It now happens once, at construction, instead of being rediscovered on every full-tree rebuild. Two of the three raw constructions in lambda.ml remain - offset_ref and mk_builtin. Neither is a tidy-up: mk_builtin makes constant guards fold at production, which is only safe since guards became data, and offset_ref is untested. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W8g8qwBARAcvW9MyuKQq8H
1 parent 247619d commit 55d44fd

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

compiler/ml/lambda.ml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,8 +1043,9 @@ let rec apply ?(ap_transformed_jsx = false) fn args (ap_info : ap_info) : t =
10431043
match is_eta_conversion_exn params inner_args args with
10441044
| args ->
10451045
let loc = ap_info.ap_loc in
1046-
Lprim
1047-
{primitive = wrap; args = [Lprim {primitive_call with args; loc}]; loc}
1046+
prim ~primitive:wrap
1047+
~args:[prim ~primitive:primitive_call.primitive ~args loc]
1048+
loc
10481049
| exception Not_simple_form ->
10491050
Lapply {ap_func = fn; ap_args = args; ap_info; ap_transformed_jsx})
10501051
| Lfunction
@@ -1053,7 +1054,7 @@ let rec apply ?(ap_transformed_jsx = false) fn args (ap_info : ap_info) : t =
10531054
body = Lprim ({primitive = _; args = inner_args} as primitive_call);
10541055
} -> (
10551056
match is_eta_conversion_exn params inner_args args with
1056-
| args -> Lprim {primitive_call with args; loc = ap_info.ap_loc}
1057+
| args -> prim ~primitive:primitive_call.primitive ~args ap_info.ap_loc
10571058
| exception _ ->
10581059
Lapply {ap_func = fn; ap_args = args; ap_info; ap_transformed_jsx})
10591060
| Lfunction
@@ -1066,7 +1067,7 @@ let rec apply ?(ap_transformed_jsx = false) fn args (ap_info : ap_info) : t =
10661067
} -> (
10671068
match is_eta_conversion_exn params inner_args args with
10681069
| args ->
1069-
Lsequence (Lprim {primitive_call with args; loc = ap_info.ap_loc}, const)
1070+
seq (prim ~primitive:primitive_call.primitive ~args ap_info.ap_loc) const
10701071
| exception _ ->
10711072
Lapply {ap_func = fn; ap_args = args; ap_info; ap_transformed_jsx}
10721073
(* | Lfunction {params;body} when Ext_list.same_length params args ->
@@ -1075,7 +1076,7 @@ let rec apply ?(ap_transformed_jsx = false) fn args (ap_info : ap_info) : t =
10751076
) params args body *)
10761077
(* TODO: more rigirous analysis on [let_kind] *))
10771078
| Llet (kind, id, e, (Lfunction _ as fn)) ->
1078-
Llet (kind, id, e, apply fn args ap_info ~ap_transformed_jsx)
1079+
let_ kind id e (apply fn args ap_info ~ap_transformed_jsx)
10791080
(* | Llet (kind0, id0, e0, Llet (kind,id, e, (Lfunction _ as fn))) ->
10801081
Llet(kind0,id0,e0,Llet (kind, id, e, apply fn args loc status)) *)
10811082
| _ -> Lapply {ap_func = fn; ap_args = args; ap_info; ap_transformed_jsx}

0 commit comments

Comments
 (0)