Skip to content

Commit 32f6ff2

Browse files
committed
Eta conversion bug (#223)
* fix a bug in such case ``` f x --> function(y){ return f(x,y)} ``` only when x is a variable makes sense
1 parent 370de8c commit 32f6ff2

10 files changed

+178
-15
lines changed

jscomp/lam_pass_alpha_conversion.ml

+29-7
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,35 @@ let alpha_conversion (meta : Lam_stats.meta) (lam : Lambda.lambda) : Lambda.lamb
4141
List.map simpl ll, {info with apply_status = Full} )
4242
else if x > len
4343
then
44-
let extra_args = Ext_list.init (x - len) (fun _ -> (Ident.create "param")) in
45-
Lfunction(Curried, extra_args,
46-
Lapply(simpl l1,
47-
List.map simpl ll @
48-
List.map (fun x -> Lambda.Lvar x) extra_args ,
49-
{info with apply_status = Full}
50-
))
44+
(* Lapply(simpl l1, List.map simpl ll, info ) *)
45+
let extra_args = Ext_list.init (x - len)
46+
(fun _ -> (Ident.create "param")) in
47+
let fn = simpl l1 in
48+
let args = List.map simpl ll in
49+
let extra_lambdas = List.map (fun x -> Lambda.Lvar x) extra_args in
50+
let args, bindings =
51+
List.fold_right (fun lam (acc, bind) ->
52+
match lam with
53+
| Lambda.Lvar _
54+
| Lconst (Const_base _ | Const_pointer _ | Const_immstring _ )
55+
| Lprim (Lambda.Pfield (_), [Lprim (Lambda.Pgetglobal _, _)] )
56+
| Lfunction _
57+
->
58+
(lam :: acc, bind)
59+
| _ ->
60+
let v = Ident.create Literals.partial_arg in
61+
(Lambda.Lvar v :: acc), ((v, lam) :: bind)
62+
) args ([],[]) in
63+
(* let args, bindings = args, [] in *)
64+
let rest : Lambda.lambda =
65+
Lfunction(Curried, extra_args,
66+
Lapply(fn,
67+
args @ extra_lambdas ,
68+
{info with apply_status = Full}
69+
)) in
70+
List.fold_left (fun lam (id,x) ->
71+
Lambda.Llet (Strict, id, x,lam)
72+
) rest bindings
5173
(*
5274
let f x y = x + y
5375
Invariant: there is no currying

jscomp/lam_pass_lets_dce.ml

+4-2
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,10 @@ let lets_helper (count_var : Ident.t -> used_info) lam =
165165
| {times = 1; captured = false }, _
166166
| {times = 1; captured = true }, (Lconst _ | Lvar _)
167167
| _, (Lconst (Const_base (
168-
Const_int _ | Const_char _ | Const_float _ | Const_int32 _
169-
| Const_nativeint _ )))
168+
Const_int _ | Const_char _ | Const_float _ | Const_int32 _
169+
| Const_nativeint _ ))
170+
(* | Lprim (Lambda.Pfield (_), [Lprim (Lambda.Pgetglobal _, _)] ) *)
171+
)
170172
(* Const_int64 is no longer primitive
171173
Note for some constant which is not
172174
inlined, we can still record it and

jscomp/literals.ml

+3
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ let js_type_string = "string"
2525
let js_type_object = "object"
2626
let js_undefined = "undefined"
2727
let js_prop_length = "length"
28+
29+
let param = "param"
30+
let partial_arg = "partial_arg"

jscomp/literals.mli

+3
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ val js_type_string : string
2424
val js_type_object : string
2525
val js_undefined : string
2626
val js_prop_length : string
27+
28+
val param : string
29+
val partial_arg : string

jscomp/stdlib/lexing.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@ var zero_pos = /* record */[
4747
];
4848

4949
function from_function(f) {
50+
var partial_arg = new Array(512);
5051
return /* record */[
5152
function (param) {
5253
var read_fun = f;
53-
var aux_buffer = new Array(512);
54+
var aux_buffer = partial_arg;
5455
var lexbuf = param;
5556
var read = Caml_curry.app2(read_fun, aux_buffer, aux_buffer.length);
5657
var n = read > 0 ? read : (lexbuf[/* lex_eof_reached */8] = /* true */1, 0);

jscomp/test/.depend

+4
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ obj_test.cmo : mt.cmi
244244
obj_test.cmx : mt.cmx
245245
of_string_test.cmo : mt.cmi
246246
of_string_test.cmx : mt.cmx
247+
pr_regression_test.cmo : mt.cmi
248+
pr_regression_test.cmx : mt.cmx
247249
primitive_reg_test.cmo :
248250
primitive_reg_test.cmx :
249251
printf_sim.cmo : ../stdlib/printf.cmi
@@ -736,6 +738,8 @@ obj_test.cmo : mt.cmi
736738
obj_test.cmj : mt.cmj
737739
of_string_test.cmo : mt.cmi
738740
of_string_test.cmj : mt.cmj
741+
pr_regression_test.cmo : mt.cmi
742+
pr_regression_test.cmj : mt.cmj
739743
primitive_reg_test.cmo :
740744
primitive_reg_test.cmj :
741745
printf_sim.cmo : ../stdlib/printf.cmi

jscomp/test/pr_regression_test.js

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Generated CODE, PLEASE EDIT WITH CARE
2+
'use strict';
3+
4+
var Mt = require("./mt");
5+
var Caml_curry = require("../runtime/caml_curry");
6+
7+
var v = [3];
8+
9+
function f(h) {
10+
++ v[0];
11+
var partial_arg = 3;
12+
return function (param) {
13+
return Caml_curry.app2(h, partial_arg, param);
14+
};
15+
}
16+
17+
f(function (prim, prim$1) {
18+
return prim + prim$1;
19+
});
20+
21+
f(function (prim, prim$1) {
22+
return prim + prim$1;
23+
});
24+
25+
var a = v[0];
26+
27+
var v$1 = [3];
28+
29+
function f$1(h) {
30+
++ v$1[0];
31+
var partial_arg = 3;
32+
return function (param) {
33+
return Caml_curry.app2(h, partial_arg, param);
34+
};
35+
}
36+
37+
f$1(function (prim, prim$1) {
38+
return prim + prim$1;
39+
});
40+
41+
f$1(function (prim, prim$1) {
42+
return prim + prim$1;
43+
});
44+
45+
var b = v$1[0];
46+
47+
var v$2 = [3];
48+
49+
function f$2(h) {
50+
return Caml_curry.app2(h, 2, (++ v$2[0], 3));
51+
}
52+
53+
f$2(function (prim, prim$1) {
54+
return prim + prim$1;
55+
});
56+
57+
f$2(function (prim, prim$1) {
58+
return prim + prim$1;
59+
});
60+
61+
var c = v$2[0];
62+
63+
Mt.from_pair_suites("pr_regression_test.ml", /* :: */[
64+
/* tuple */[
65+
"partial",
66+
function () {
67+
return /* Eq */{
68+
0: /* tuple */[
69+
5,
70+
5,
71+
5
72+
],
73+
1: /* tuple */[
74+
a,
75+
b,
76+
c
77+
],
78+
length: 2,
79+
tag: 0
80+
};
81+
}
82+
],
83+
/* [] */0
84+
]);
85+
86+
exports.a = a;
87+
exports.b = b;
88+
exports.c = c;
89+
/* Not a pure module */

jscomp/test/pr_regression_test.ml

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
3+
let a =
4+
let v = ref 3 in
5+
let action () = incr v in
6+
let f h =
7+
(fun x y -> h x y) (action (); 3) in
8+
ignore @@ f (+);
9+
ignore @@ f (+);
10+
!v
11+
12+
let b =
13+
let v = ref 3 in
14+
let action () = incr v in
15+
let f h =
16+
(fun x y -> h x y) (action (); 3) in
17+
ignore @@ f (+);
18+
ignore @@ f (+);
19+
!v
20+
21+
let c =
22+
let v = ref 3 in
23+
let action () = incr v in
24+
let f h =
25+
(fun x y -> h x y) 2 (action (); 3) in
26+
ignore @@ f (+);
27+
ignore @@ f (+);
28+
!v
29+
30+
(* ;; Printf.printf "%d%d%d\n" a b c *)
31+
32+
;; Mt.from_pair_suites __FILE__ Mt.[
33+
"partial", (fun _ -> Eq((5,5,5), (a,b,c)))
34+
]
35+
36+

jscomp/test/qcc.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -2180,11 +2180,13 @@ function main() {
21802180
var f = Sys.argv.length < 2 ? "-blk" : Sys.argv[1];
21812181
switch (f) {
21822182
case "-blk" :
2183+
var partial_arg_000 = [0];
2184+
var partial_arg = /* tuple */[
2185+
partial_arg_000,
2186+
0
2187+
];
21832188
var c = function (param) {
2184-
return block(/* tuple */[
2185-
[0],
2186-
0
2187-
], param);
2189+
return block(partial_arg, param);
21882190
};
21892191
var stk = /* [] */0;
21902192
opos[0] = 0;

jscomp/test/test.mllib

+2-1
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,5 @@ printf_sim
213213
test_external_unit
214214
ext_array
215215
int32_test
216-
hamming_test
216+
hamming_test
217+
pr_regression_test

0 commit comments

Comments
 (0)