Skip to content

Commit cfed01f

Browse files
authored
Turn off transformation for closures inside loops (#6480)
The scope of `var` is per-function, requiring a transformation for closures inside loops when capturing loop variables. This PR turns off the transformation.
1 parent 7bf97d9 commit cfed01f

30 files changed

+150
-398
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
- Fix indent for returned/thrown/wrapped in parentheses objects in generated js code. https://github.com/rescript-lang/rescript-compiler/pull/6746
3333
- Fix indent in generated js code. https://github.com/rescript-lang/rescript-compiler/pull/6747
3434
- In generated code, use `let` instead of `var`. https://github.com/rescript-lang/rescript-compiler/pull/6102
35+
- Turn off transformation for closures inside loops when capturing loop variables, now that `let` is emitted instead of `var`. https://github.com/rescript-lang/rescript-compiler/pull/6480
3536

3637
# 11.1.0
3738

jscomp/core/j.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,14 @@ and statement_desc =
254254
(* Function declaration and Variable declaration *)
255255
| Exp of expression
256256
| If of expression * block * block
257-
| While of label option * expression * block * Js_closure.t
257+
| While of label option * expression * block
258258
(* check if it contains loop mutable values, happens in nested loop *)
259259
| ForRange of
260260
for_ident_expression option
261261
* finish_ident_expression
262262
* for_ident
263263
* for_direction
264264
* block
265-
* Js_closure.t
266265
| Continue of label
267266
| Break (* only used when inline a fucntion *)
268267
| Return of expression

jscomp/core/js_closure.ml

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

jscomp/core/js_closure.mli

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

jscomp/core/js_dump.ml

Lines changed: 8 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,6 @@ let exp_need_paren (e : J.expression) =
164164
| Await _ -> false
165165
| Tagged_template _ -> false
166166

167-
let comma_idents (cxt : cxt) f ls = iter_lst cxt f ls Ext_pp_scope.ident comma
168-
169-
let pp_paren_params (inner_cxt : cxt) (f : Ext_pp.t) (lexical : Ident.t list) :
170-
unit =
171-
P.string f L.lparen;
172-
let (_ : cxt) = comma_idents inner_cxt f lexical in
173-
P.string f L.rparen
174-
175167
(** Print as underscore for unused vars, may not be
176168
needed in the future *)
177169
(* let ipp_ident cxt f id (un_used : bool) =
@@ -381,10 +373,9 @@ and pp_function ~return_unit ~async ~is_method cxt (f : P.t) ~fn_state
381373
P.space f;
382374
P.brace_vgroup f 1 (fun _ -> function_body ~return_unit cxt f b)
383375
in
384-
let lexical : Set_ident.t = Js_fun_env.get_lexical_scope env in
385-
let enclose lexical =
386-
let handle lexical =
387-
if Set_ident.is_empty lexical then (
376+
let enclose () =
377+
let handle () =
378+
(
388379
match fn_state with
389380
| Is_return ->
390381
return_sp f;
@@ -408,46 +399,10 @@ and pp_function ~return_unit ~async ~is_method cxt (f : P.t) ~fn_state
408399
P.space f;
409400
ignore (Ext_pp_scope.ident inner_cxt f x : cxt);
410401
param_body ())
411-
else
412-
(* print our closure as
413-
{[(function(x,y){ return function(..){...}} (x,y))]}
414-
Maybe changed to `let` in the future
415-
*)
416-
let lexical = Set_ident.elements lexical in
417-
(match fn_state with
418-
| Is_return -> return_sp f
419-
| No_name _ -> ()
420-
| Name_non_top name | Name_top name ->
421-
ignore (pp_var_assign inner_cxt f name : cxt));
422-
if async then P.string f L.await;
423-
P.string f L.lparen;
424-
P.string f (L.function_async ~async);
425-
pp_paren_params inner_cxt f lexical;
426-
P.brace_vgroup f 0 (fun _ ->
427-
return_sp f;
428-
P.string f (L.function_async ~async);
429-
P.space f;
430-
(match fn_state with
431-
| Is_return | No_name _ -> ()
432-
| Name_non_top x | Name_top x ->
433-
ignore (Ext_pp_scope.ident inner_cxt f x));
434-
param_body ());
435-
pp_paren_params inner_cxt f lexical;
436-
P.string f L.rparen;
437-
match fn_state with
438-
| Is_return | No_name _ -> () (* expression *)
439-
| _ -> semi f
440-
(* has binding, a statement *)
441402
in
442-
handle
443-
(match fn_state with
444-
| (Name_top name | Name_non_top name) when Set_ident.mem lexical name
445-
->
446-
(*TODO: when calculating lexical we should not include itself *)
447-
Set_ident.remove lexical name
448-
| _ -> lexical)
403+
handle ()
449404
in
450-
enclose lexical;
405+
enclose ();
451406
outer_cxt
452407

453408
(* Assume the cond would not change the context,
@@ -1065,7 +1020,7 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
10651020
P.string f L.else_;
10661021
P.space f;
10671022
brace_block cxt f s2)
1068-
| While (label, e, s, _env) ->
1023+
| While (label, e, s) ->
10691024
(* FIXME: print scope as well *)
10701025
(match label with
10711026
| Some i ->
@@ -1093,7 +1048,7 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
10931048
let cxt = brace_block cxt f s in
10941049
semi f;
10951050
cxt
1096-
| ForRange (for_ident_expression, finish, id, direction, s, env) ->
1051+
| ForRange (for_ident_expression, finish, id, direction, s) ->
10971052
let action cxt =
10981053
P.vgroup f 0 (fun _ ->
10991054
let cxt =
@@ -1164,24 +1119,7 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
11641119
in
11651120
brace_block cxt f s)
11661121
in
1167-
let lexical = Js_closure.get_lexical_scope env in
1168-
if Set_ident.is_empty lexical then action cxt
1169-
else
1170-
(* unlike function,
1171-
[print for loop] has side effect,
1172-
we should take it out
1173-
*)
1174-
let inner_cxt = Ext_pp_scope.merge cxt lexical in
1175-
let lexical = Set_ident.elements lexical in
1176-
P.vgroup f 0 (fun _ ->
1177-
P.string f L.lparen;
1178-
P.string f L.function_;
1179-
pp_paren_params inner_cxt f lexical;
1180-
let cxt = P.brace_vgroup f 0 (fun _ -> action inner_cxt) in
1181-
pp_paren_params inner_cxt f lexical;
1182-
P.string f L.rparen;
1183-
semi f;
1184-
cxt)
1122+
action cxt
11851123
| Continue s ->
11861124
continue f s;
11871125
cxt

jscomp/core/js_fold.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,12 @@ class fold =
217217
let _self = _self#block _x1 in
218218
let _self = _self#block _x2 in
219219
_self
220-
| While (_x0, _x1, _x2, _x3) ->
220+
| While (_x0, _x1, _x2) ->
221221
let _self = option (fun _self -> _self#label) _self _x0 in
222222
let _self = _self#expression _x1 in
223223
let _self = _self#block _x2 in
224224
_self
225-
| ForRange (_x0, _x1, _x2, _x3, _x4, _x5) ->
225+
| ForRange (_x0, _x1, _x2, _x3, _x4) ->
226226
let _self =
227227
option (fun _self -> _self#for_ident_expression) _self _x0
228228
in

jscomp/core/js_fun_env.ml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ type immutable_mask =
4444

4545
type t = {
4646
mutable unbounded : Set_ident.t;
47-
mutable bound_loop_mutable_values : Set_ident.t;
4847
used_mask : bool array;
4948
immutable_mask : immutable_mask;
5049
}
@@ -58,7 +57,6 @@ let make ?immutable_mask n =
5857
(match immutable_mask with
5958
| Some x -> Immutable_mask x
6059
| None -> All_immutable_and_no_tail_call);
61-
bound_loop_mutable_values = Set_ident.empty;
6260
}
6361

6462
let no_tailcall x =
@@ -92,13 +90,3 @@ let set_unbounded env v =
9290
(* if Set_ident.is_empty env.bound then *)
9391
env.unbounded <- v
9492
(* else assert false *)
95-
96-
let set_lexical_scope env bound_loop_mutable_values =
97-
env.bound_loop_mutable_values <- bound_loop_mutable_values
98-
99-
let get_lexical_scope env = env.bound_loop_mutable_values
100-
101-
(* TODO: can be refined if it
102-
only enclose toplevel variables
103-
*)
104-
(* let is_empty t = Set_ident.is_empty t.unbounded *)

jscomp/core/js_fun_env.mli

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ val no_tailcall : t -> bool list
3636

3737
val set_unbounded : t -> Set_ident.t -> unit
3838

39-
val set_lexical_scope : t -> Set_ident.t -> unit
40-
41-
val get_lexical_scope : t -> Set_ident.t
42-
4339
(* val to_string : t -> string *)
4440

4541
val mark_unused : t -> int -> unit

jscomp/core/js_pass_scope.ml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,6 @@ let record_scope_pass =
173173
due to the recursive thing
174174
*)
175175
Js_fun_env.set_unbounded env closured_idents';
176-
let lexical_scopes =
177-
Set_ident.(inter closured_idents' state.loop_mutable_values)
178-
in
179-
Js_fun_env.set_lexical_scope env lexical_scopes;
180176
(* tailcall , note that these varibles are used in another pass *)
181177
{
182178
state with
@@ -242,7 +238,7 @@ let record_scope_pass =
242238
statement =
243239
(fun self state x ->
244240
match x.statement_desc with
245-
| ForRange (_, _, loop_id, _, _, a_env) ->
241+
| ForRange (_, _, loop_id, _, _) ->
246242
(* TODO: simplify definition of For *)
247243
let {
248244
defined_idents = defined_idents';
@@ -274,8 +270,6 @@ let record_scope_pass =
274270
(diff closured_idents' defined_idents')
275271
state.loop_mutable_values)
276272
in
277-
let () = Js_closure.set_lexical_scope a_env lexical_scope in
278-
(* set scope *)
279273
{
280274
state with
281275
used_idents = Set_ident.union state.used_idents used_idents';
@@ -293,7 +287,7 @@ let record_scope_pass =
293287
closured_idents =
294288
Set_ident.union state.closured_idents lexical_scope;
295289
}
296-
| While (_label, pred, body, _env) ->
290+
| While (_label, pred, body) ->
297291
with_in_loop
298292
(self.block self
299293
(with_in_loop (self.expression self state pred) true)

jscomp/core/js_record_fold.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,12 @@ let statement_desc : 'a. ('a, statement_desc) fn =
223223
let st = _self.block _self st _x1 in
224224
let st = _self.block _self st _x2 in
225225
st
226-
| While (_x0, _x1, _x2, _x3) ->
226+
| While (_x0, _x1, _x2) ->
227227
let st = option label _self st _x0 in
228228
let st = _self.expression _self st _x1 in
229229
let st = _self.block _self st _x2 in
230230
st
231-
| ForRange (_x0, _x1, _x2, _x3, _x4, _x5) ->
231+
| ForRange (_x0, _x1, _x2, _x3, _x4) ->
232232
let st = option for_ident_expression _self st _x0 in
233233
let st = finish_ident_expression _self st _x1 in
234234
let st = _self.for_ident _self st _x2 in

jscomp/core/js_record_iter.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,11 @@ let statement_desc : statement_desc fn =
163163
_self.expression _self _x0;
164164
_self.block _self _x1;
165165
_self.block _self _x2
166-
| While (_x0, _x1, _x2, _x3) ->
166+
| While (_x0, _x1, _x2) ->
167167
option label _self _x0;
168168
_self.expression _self _x1;
169169
_self.block _self _x2
170-
| ForRange (_x0, _x1, _x2, _x3, _x4, _x5) ->
170+
| ForRange (_x0, _x1, _x2, _x3, _x4) ->
171171
option for_ident_expression _self _x0;
172172
finish_ident_expression _self _x1;
173173
_self.for_ident _self _x2;

jscomp/core/js_record_map.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,18 +221,18 @@ let statement_desc : statement_desc fn =
221221
let _x1 = _self.block _self _x1 in
222222
let _x2 = _self.block _self _x2 in
223223
If (_x0, _x1, _x2)
224-
| While (_x0, _x1, _x2, _x3) ->
224+
| While (_x0, _x1, _x2) ->
225225
let _x0 = option label _self _x0 in
226226
let _x1 = _self.expression _self _x1 in
227227
let _x2 = _self.block _self _x2 in
228-
While (_x0, _x1, _x2, _x3)
229-
| ForRange (_x0, _x1, _x2, _x3, _x4, _x5) ->
228+
While (_x0, _x1, _x2)
229+
| ForRange (_x0, _x1, _x2, _x3, _x4) ->
230230
let _x0 = option for_ident_expression _self _x0 in
231231
let _x1 = finish_ident_expression _self _x1 in
232232
let _x2 = _self.for_ident _self _x2 in
233233
let _x3 = for_direction _self _x3 in
234234
let _x4 = _self.block _self _x4 in
235-
ForRange (_x0, _x1, _x2, _x3, _x4, _x5)
235+
ForRange (_x0, _x1, _x2, _x3, _x4)
236236
| Continue _x0 ->
237237
let _x0 = label _self _x0 in
238238
Continue _x0

jscomp/core/js_stmt_make.ml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,17 +318,15 @@ let if_ ?comment ?declaration ?else_ (e : J.expression) (then_ : J.block) : t =
318318
let assign ?comment id e : t =
319319
{ statement_desc = J.Exp (E.assign (E.var id) e); comment }
320320

321-
let while_ ?comment ?label ?env (e : E.t) (st : J.block) : t =
322-
let env = match env with None -> Js_closure.empty () | Some x -> x in
323-
{ statement_desc = While (label, e, st, env); comment }
321+
let while_ ?comment ?label (e : E.t) (st : J.block) : t =
322+
{ statement_desc = While (label, e, st); comment }
324323

325-
let for_ ?comment ?env for_ident_expression finish_ident_expression id direction
324+
let for_ ?comment for_ident_expression finish_ident_expression id direction
326325
(b : J.block) : t =
327-
let env = match env with None -> Js_closure.empty () | Some x -> x in
328326
{
329327
statement_desc =
330328
ForRange
331-
(for_ident_expression, finish_ident_expression, id, direction, b, env);
329+
(for_ident_expression, finish_ident_expression, id, direction, b);
332330
comment;
333331
}
334332

jscomp/core/js_stmt_make.mli

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,12 @@ val assign : ?comment:string -> J.ident -> J.expression -> t
133133
val while_ :
134134
?comment:string ->
135135
?label:J.label ->
136-
?env:Js_closure.t ->
137136
J.expression ->
138137
J.block ->
139138
t
140139

141140
val for_ :
142141
?comment:string ->
143-
?env:Js_closure.t ->
144142
J.for_ident_expression option ->
145143
J.finish_ident_expression ->
146144
J.for_ident ->

0 commit comments

Comments
 (0)