Skip to content

Commit 1642c25

Browse files
authored
New feature: break/continue in loops (#8348)
* New feature: break/continue in loops * Fix GenType tests * Remove not working new build test * Analysis fixes * Fix braced break/continue * Fix unreachable code check
1 parent cb9e2ec commit 1642c25

114 files changed

Lines changed: 1134 additions & 274 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
// Exmple of several DCE checks operating in unison
22

3-
type break =
3+
type break_ =
44
| IfNeed
55
| Never
66
| Always
77

88
type t = {
9-
break: break,
9+
break_: break_,
1010
doc: string,
1111
}
1212

1313
type rec stack =
1414
| Empty
1515
| Cons(t, stack)
1616

17-
let group = (~break=IfNeed, doc) => {break: break, doc: doc}
17+
let group = (~break_=IfNeed, doc) => {break_, doc: doc}
1818

1919
let rec fits = (w, stack) =>
2020
switch stack {
@@ -25,8 +25,8 @@ let rec fits = (w, stack) =>
2525

2626
let rec toString = (~width, stack) =>
2727
switch stack {
28-
| Cons({break, doc}, stack) =>
29-
switch break {
28+
| Cons({break_, doc}, stack) =>
29+
switch break_ {
3030
| IfNeed => (fits(width, stack) ? "fits " : "no ") ++ (stack |> toString(~width=width - 1))
3131
| Never => "never " ++ (doc ++ (stack |> toString(~width=width - 1)))
3232
| Always => "always " ++ (doc ++ (stack |> toString(~width=width - 1)))
@@ -35,5 +35,5 @@ let rec toString = (~width, stack) =>
3535
}
3636

3737
toString(~width=80, Empty)
38-
toString(~width=80, Cons(group(~break=Never, "abc"), Empty))
39-
toString(~width=80, Cons(group(~break=Always, "d"), Empty))
38+
toString(~width=80, Cons(group(~break_=Never, "abc"), Empty))
39+
toString(~width=80, Cons(group(~break_=Always, "d"), Empty))

analysis/examples/larger-project/src/res_doc.res

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,8 @@ let debug = t => {
330330
text(")"),
331331
}),
332332
)
333-
| LineBreak(break) =>
334-
let breakTxt = switch break {
333+
| LineBreak(break_) =>
334+
let breakTxt = switch break_ {
335335
| Classic => "Classic"
336336
| Soft => "Soft"
337337
| Hard => "Hard"

analysis/reanalyze/src/SideEffects.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ let rec exprNoSideEffects (expr : Typedtree.expression) =
2626
| Texp_ident _ | Texp_constant _ -> true
2727
| Texp_construct (_, _, el) -> el |> List.for_all exprNoSideEffects
2828
| Texp_function _ -> true
29+
(* Loop control changes whether subsequent code in the enclosing loop runs,
30+
so it should not be treated as a removable pure expression. *)
31+
| Texp_break | Texp_continue -> false
2932
| Texp_apply {funct = {exp_desc = Texp_ident (path, _, _)}; args}
3033
when path |> pathIsWhitelistedForSideEffects ->
3134
args |> List.for_all (fun (_, eo) -> eo |> exprOptNoSideEffects)

analysis/src/DumpAst.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ and printExprItem expr ~pos ~indentation =
170170
|> String.concat "\n")
171171
| Pexp_ident {txt} ->
172172
"Pexp_ident:" ^ (Utils.flattenLongIdent txt |> SharedTypes.ident)
173+
| Pexp_break -> "Pexp_break"
174+
| Pexp_continue -> "Pexp_continue"
173175
| Pexp_apply {funct = expr; args} ->
174176
let printLabel labelled ~pos =
175177
match labelled with

analysis/src/Utils.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ let identifyPexp pexp =
9898
| Pexp_array _ -> "Pexp_array"
9999
| Pexp_ifthenelse _ -> "Pexp_ifthenelse"
100100
| Pexp_sequence _ -> "Pexp_sequence"
101+
| Pexp_break -> "Pexp_break"
102+
| Pexp_continue -> "Pexp_continue"
101103
| Pexp_while _ -> "Pexp_while"
102104
| Pexp_for _ -> "Pexp_for"
103105
| Pexp_constraint _ -> "Pexp_constraint"

compiler/core/j.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,23 +249,25 @@ and case_clause = {
249249

250250
and string_clause = Ast_untagged_variants.tag_type * case_clause
251251
and int_clause = int * case_clause
252+
and label = string
252253

253254
and statement_desc =
254255
| Block of block
255256
| Variable of variable_declaration
256257
(* Function declaration and Variable declaration *)
257258
| Exp of expression
258259
| If of expression * block * block
259-
| While of expression * block
260+
| While of label option * expression * block
260261
(* check if it contains loop mutable values, happens in nested loop *)
261262
| ForRange of
262-
for_ident_expression option
263+
label option
264+
* for_ident_expression option
263265
* finish_ident_expression
264266
* for_ident
265267
* for_direction
266268
* block
267-
| Continue
268-
| Break (* only used when inline a fucntion *)
269+
| Continue of label option
270+
| Break of label option (* only used when inline a fucntion *)
269271
| Return of expression
270272
(* Here we need track back a bit ?, move Return to Function ...
271273
Then we can only have one Return, which is not good *)

compiler/core/js_analyzer.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ let no_side_effect_obj =
132132
statement =
133133
(fun self s ->
134134
match s.statement_desc with
135-
| Throw _ | Debugger | Break | Variable _ | Continue ->
135+
| Throw _ | Debugger | Break _ | Variable _ | Continue _ ->
136136
raise_notrace Not_found
137137
| Exp e -> self.expression self e
138138
| Int_switch _ | String_switch _ | ForRange _ | If _ | While _ | Block _
@@ -250,12 +250,12 @@ and eq_statement ({statement_desc = x0} : J.statement)
250250
| Return b -> eq_expression a b
251251
| _ -> false)
252252
| Debugger -> y0 = Debugger
253-
| Break -> y0 = Break
253+
| Break label -> y0 = Break label
254254
| Block xs0 -> (
255255
match y0 with
256256
| Block ys0 -> eq_block xs0 ys0
257257
| _ -> false)
258-
| Variable _ | If _ | While _ | ForRange _ | Continue | Int_switch _
258+
| Variable _ | If _ | While _ | ForRange _ | Continue _ | Int_switch _
259259
| String_switch _ | Throw _ | Try _ ->
260260
false
261261

compiler/core/js_dump.ml

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,6 @@ let debugger_nl f =
237237
semi f;
238238
P.newline f
239239

240-
let break_nl f =
241-
P.string f L.break;
242-
semi f;
243-
P.newline f
244-
245-
let continue f =
246-
P.string f L.continue;
247-
semi f
248-
249240
let formal_parameter_list cxt f l = iter_lst cxt f l Ext_pp_scope.ident comma_sp
250241

251242
(* IdentMap *)
@@ -1390,9 +1381,18 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
13901381
P.string f L.else_;
13911382
P.space f;
13921383
brace_block cxt f s2)
1393-
| While (e, s) ->
1384+
| While (label, e, s) ->
13941385
(* FIXME: print scope as well *)
13951386
let cxt =
1387+
let cxt =
1388+
match label with
1389+
| None -> cxt
1390+
| Some label ->
1391+
P.string f label;
1392+
P.string f L.colon;
1393+
P.space f;
1394+
cxt
1395+
in
13961396
match e.expression_desc with
13971397
| Number (Int {i = 1l}) ->
13981398
P.string f L.while_;
@@ -1412,9 +1412,18 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
14121412
let cxt = brace_block cxt f s in
14131413
semi f;
14141414
cxt
1415-
| ForRange (for_ident_expression, finish, id, direction, s) ->
1415+
| ForRange (label, for_ident_expression, finish, id, direction, s) ->
14161416
let action cxt =
14171417
P.vgroup f 0 (fun _ ->
1418+
let cxt =
1419+
match label with
1420+
| None -> cxt
1421+
| Some label ->
1422+
P.string f label;
1423+
P.string f L.colon;
1424+
P.space f;
1425+
cxt
1426+
in
14181427
let cxt =
14191428
P.group f 0 (fun _ ->
14201429
(* The only place that [semi] may have semantics here *)
@@ -1489,15 +1498,28 @@ and statement_desc top cxt f (s : J.statement_desc) : cxt =
14891498
brace_block cxt f s)
14901499
in
14911500
action cxt
1492-
| Continue ->
1493-
continue f;
1501+
| Continue label ->
1502+
P.string f L.continue;
1503+
(match label with
1504+
| None -> ()
1505+
| Some label ->
1506+
P.space f;
1507+
P.string f label);
1508+
semi f;
14941509
cxt
14951510
(* P.newline f; #2642 *)
14961511
| Debugger ->
14971512
debugger_nl f;
14981513
cxt
1499-
| Break ->
1500-
break_nl f;
1514+
| Break label ->
1515+
P.string f L.break;
1516+
(match label with
1517+
| None -> ()
1518+
| Some label ->
1519+
P.space f;
1520+
P.string f label);
1521+
semi f;
1522+
P.newline f;
15011523
cxt
15021524
| Return e -> (
15031525
match e.expression_desc with

compiler/core/js_fold.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,11 @@ class fold =
228228
let _self = _self#block _x1 in
229229
let _self = _self#block _x2 in
230230
_self
231-
| While (_x0, _x1) ->
231+
| While (_label, _x0, _x1) ->
232232
let _self = _self#expression _x0 in
233233
let _self = _self#block _x1 in
234234
_self
235-
| ForRange (_x0, _x1, _x2, _x3, _x4) ->
235+
| ForRange (_label, _x0, _x1, _x2, _x3, _x4) ->
236236
let _self =
237237
option (fun _self -> _self#for_ident_expression) _self _x0
238238
in
@@ -241,8 +241,8 @@ class fold =
241241
let _self = _self#for_direction _x3 in
242242
let _self = _self#block _x4 in
243243
_self
244-
| Continue -> _self
245-
| Break -> _self
244+
| Continue _ -> _self
245+
| Break _ -> _self
246246
| Return _x0 ->
247247
let _self = _self#expression _x0 in
248248
_self

compiler/core/js_pass_scope.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ let record_scope_pass =
238238
statement =
239239
(fun self state x ->
240240
match x.statement_desc with
241-
| ForRange (_, _, loop_id, _, _) ->
241+
| ForRange (_, _, _, loop_id, _, _) ->
242242
(* TODO: simplify definition of For *)
243243
let {
244244
defined_idents = defined_idents';
@@ -287,7 +287,7 @@ let record_scope_pass =
287287
closured_idents =
288288
Set_ident.union state.closured_idents lexical_scope;
289289
}
290-
| While (pred, body) ->
290+
| While (_, pred, body) ->
291291
with_in_loop
292292
(self.block self
293293
(with_in_loop (self.expression self state pred) true)

0 commit comments

Comments
 (0)