Skip to content

Commit bdc637a

Browse files
committed
Expose lifter problem with loops
1 parent 7e80df3 commit bdc637a

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,9 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder:
396396

397397
case Label(lbl, bod, rst) =>
398398
scope.allocateName(lbl)
399+
400+
// [fixme:0] TODO check scope and allocate local variables here (see: https://github.com/hkust-taco/mlscript/pull/293#issuecomment-2792229849)
401+
399402
doc" # ${getVar(lbl)}: while (true) { #{ ${
400403
returningTerm(bod, endSemi = false)
401404
} # break; #} # }${returningTerm(rst, endSemi)}"
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
:js
2+
:lift
3+
4+
5+
let fs = []
6+
//│ fs = []
7+
8+
fun foo() =
9+
let x = 1
10+
while x < 5 do
11+
set x += 1
12+
fs.push of () => x
13+
14+
:expect 5
15+
foo()
16+
fs.0()
17+
//│ = 5
18+
19+
20+
let fs = []
21+
//│ fs = []
22+
23+
fun foo() =
24+
let i = 1
25+
while i < 5 do
26+
let x = i
27+
set i += 1
28+
fs.push of () => x
29+
30+
// * Note that this also fails without lifting, as we need to fix [fixme:0]
31+
:fixme
32+
:expect 1
33+
foo()
34+
fs.0()
35+
//│ ═══[RUNTIME ERROR] Expected: '1', got: '4'
36+
//│ = 4
37+
38+
39+
:sjs
40+
fun foo() =
41+
let x = 1
42+
while true do
43+
set x += 1
44+
return () => x
45+
//│ JS (unsanitized):
46+
//│ let foo2, lambda2, lambda$2;
47+
//│ lambda$2 = function lambda$(x) {
48+
//│ return x
49+
//│ };
50+
//│ lambda2 = (undefined, function (x) {
51+
//│ return () => {
52+
//│ return lambda$2(x)
53+
//│ }
54+
//│ });
55+
//│ foo2 = function foo() {
56+
//│ let x, scrut, tmp2, tmp3;
57+
//│ x = 1;
58+
//│ tmp4: while (true) {
59+
//│ scrut = true;
60+
//│ if (scrut === true) {
61+
//│ tmp2 = x + 1;
62+
//│ x = tmp2;
63+
//│ return runtime.safeCall(lambda2(x))
64+
//│ } else {
65+
//│ tmp3 = runtime.Unit;
66+
//│ }
67+
//│ break;
68+
//│ }
69+
//│ return tmp3
70+
//│ };
71+
72+
:expect 2
73+
foo()()
74+
//│ = 2
75+
76+
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
:lift
2+
:js
3+
4+
5+
let xs = []
6+
//│ xs = []
7+
8+
fun foo() =
9+
let x = 1
10+
fun bar() = x
11+
xs.push(bar)
12+
set x = 2
13+
14+
:expect 2
15+
foo()
16+
xs.0()
17+
//│ = 2
18+
19+
20+
let xs = []
21+
//│ xs = []
22+
23+
// :sjs
24+
fun foo() =
25+
let x
26+
fun bar() = x
27+
xs.push(bar)
28+
x = 2
29+
30+
:expect 2
31+
foo()
32+
xs.0()
33+
//│ = 2
34+
35+
36+
fun foo() =
37+
let x
38+
fun bar() =
39+
x = 2
40+
[bar, () => x]
41+
42+
:expect 2
43+
let b_x = foo()
44+
b_x.0()
45+
b_x.1()
46+
//│ = 2
47+
//│ b_x = [[function], [function]]
48+
49+
50+
:sjs
51+
fun foo() =
52+
fun bar() =
53+
let x
54+
x
55+
bar
56+
//│ JS (unsanitized):
57+
//│ let bar3, foo3;
58+
//│ bar3 = function bar() {
59+
//│ let x;
60+
//│ x = undefined;
61+
//│ return x
62+
//│ };
63+
//│ foo3 = function foo() {
64+
//│ return bar3
65+
//│ };
66+
67+

0 commit comments

Comments
 (0)