Skip to content

Commit 58f81dc

Browse files
committed
Fix braced break/continue
1 parent d46525d commit 58f81dc

3 files changed

Lines changed: 60 additions & 4 deletions

File tree

compiler/core/lam_compile.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,7 +1877,9 @@ let compile output_prefix =
18771877
S.break_ ~label ()
18781878
else S.break_ ()
18791879
in
1880-
Js_output.make [stmt] ~output_finished:True)
1880+
(* [break] is accepted inside braced expressions like [{break}], so keep
1881+
the usual NeedValue invariant even though JS only has a statement form. *)
1882+
Js_output.make [stmt] ~value:E.undefined ~output_finished:True)
18811883
| Lcontinue -> (
18821884
match lambda_cxt.loop_stack with
18831885
| [] -> assert false
@@ -1892,7 +1894,7 @@ let compile output_prefix =
18921894
S.continue_ ~label ()
18931895
else S.continue_ ()
18941896
in
1895-
Js_output.make [stmt] ~output_finished:True)
1897+
Js_output.make [stmt] ~value:E.undefined ~output_finished:True)
18961898
| Lwhile (p, body) -> compile_while p body lambda_cxt
18971899
| Lfor (id, start, finish, direction, body) -> (
18981900
match (direction, finish) with

tests/tests/src/loop_control_test.mjs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,31 @@ Mocha.describe("Loop_control_test", () => {
102102
3
103103
], Belt_List.toArray(Belt_List.reverse(values)));
104104
});
105+
Mocha.test("braced break expression in value position compiles", () => {
106+
let reached = false;
107+
while (true) {
108+
break;
109+
110+
};
111+
Test_utils.eq("File \"loop_control_test.res\", line 95, characters 7-14", false, reached);
112+
});
113+
Mocha.test("braced continue expression in value position compiles", () => {
114+
let values = /* [] */0;
115+
for (let i = 0; i <= 3; ++i) {
116+
if (i === 1) {
117+
continue;
118+
}
119+
values = {
120+
hd: i,
121+
tl: values
122+
};
123+
}
124+
Test_utils.eq("File \"loop_control_test.res\", line 111, characters 7-14", [
125+
0,
126+
2,
127+
3
128+
], Belt_List.toArray(Belt_List.reverse(values)));
129+
});
105130
Mocha.test("switch inside for targets the loop", () => {
106131
let values = /* [] */0;
107132
for (let i = 0; i <= 5; ++i) {
@@ -119,7 +144,7 @@ Mocha.describe("Loop_control_test", () => {
119144
continue;
120145
}
121146
}
122-
Test_utils.eq("File \"loop_control_test.res\", line 96, characters 7-14", [
147+
Test_utils.eq("File \"loop_control_test.res\", line 125, characters 7-14", [
123148
0,
124149
2,
125150
3
@@ -143,7 +168,7 @@ Mocha.describe("Loop_control_test", () => {
143168
};
144169
}
145170
}
146-
Test_utils.eq("File \"loop_control_test.res\", line 117, characters 7-14", [
171+
Test_utils.eq("File \"loop_control_test.res\", line 146, characters 7-14", [
147172
0,
148173
2,
149174
3

tests/tests/src/loop_control_test.res

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,35 @@ describe(__MODULE__, () => {
8282
eq(__LOC__, [0, 2, 3], values.contents->Belt.List.reverse->Belt.List.toArray)
8383
})
8484

85+
test("braced break expression in value position compiles", () => {
86+
let reached = ref(false)
87+
let acceptUnit = (_: unit) => ()
88+
89+
while true {
90+
let x = {break}
91+
acceptUnit(x)
92+
reached := true
93+
}
94+
95+
eq(__LOC__, false, reached.contents)
96+
})
97+
98+
test("braced continue expression in value position compiles", () => {
99+
let values = ref(list{})
100+
let acceptUnit = (_: unit) => ()
101+
102+
for i in 0 to 3 {
103+
if i == 1 {
104+
let x = {continue}
105+
acceptUnit(x)
106+
}
107+
108+
values := list{i, ...values.contents}
109+
}
110+
111+
eq(__LOC__, [0, 2, 3], values.contents->Belt.List.reverse->Belt.List.toArray)
112+
})
113+
85114
test("switch inside for targets the loop", () => {
86115
let values = ref(list{})
87116

0 commit comments

Comments
 (0)