Skip to content

Commit 3273b80

Browse files
fix: cleanup & feedback
1 parent a354fb6 commit 3273b80

3 files changed

Lines changed: 206 additions & 36 deletions

File tree

src/transformation/visitors/switch.ts

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -65,50 +65,58 @@ export const transformSwitchStatement: FunctionVisitor<ts.SwitchStatement> = (st
6565
// Default is the not of all known case expressions
6666
let previousClause: ts.CaseOrDefaultClause;
6767
let condition: lua.Expression | undefined;
68+
let isInitialCondition = true;
6869
statement.caseBlock.clauses.forEach(clause => {
6970
if (!condition || (previousClause && containsBreakOrReturn([...previousClause.statements]))) {
7071
if (ts.isDefaultClause(clause)) {
71-
// If the default is first, or followed by a break, we can't fall into it, skip.
72+
condition = undefined;
7273
} else {
7374
condition = lua.createBinaryExpression(
7475
switchVariable,
7576
context.transformExpression(clause.expression),
7677
lua.SyntaxKind.EqualityOperator
7778
);
7879
}
79-
} else {
80-
if (ts.isDefaultClause(clause)) {
81-
// use the previous condition for the default clause
82-
} else {
83-
condition = lua.createBinaryExpression(
84-
condition,
85-
lua.createBinaryExpression(
86-
switchVariable,
87-
context.transformExpression(clause.expression),
88-
lua.SyntaxKind.EqualityOperator
89-
),
90-
lua.SyntaxKind.OrOperator
91-
);
92-
}
80+
} else if (!ts.isDefaultClause(clause)) {
81+
condition = lua.createBinaryExpression(
82+
condition,
83+
lua.createBinaryExpression(
84+
switchVariable,
85+
context.transformExpression(clause.expression),
86+
lua.SyntaxKind.EqualityOperator
87+
),
88+
lua.SyntaxKind.OrOperator
89+
);
9390
}
9491

9592
if (clause.statements.length) {
9693
if (!ts.isDefaultClause(clause) && condition) {
9794
statements.push(
98-
lua.createAssignmentStatement(
99-
conditionVariable,
100-
lua.createBinaryExpression(conditionVariable, condition, lua.SyntaxKind.OrOperator)
101-
)
95+
isInitialCondition
96+
? lua.createVariableDeclarationStatement(conditionVariable, condition)
97+
: lua.createAssignmentStatement(
98+
conditionVariable,
99+
lua.createBinaryExpression(conditionVariable, condition, lua.SyntaxKind.OrOperator)
100+
)
102101
);
102+
isInitialCondition = false;
103103
condition = undefined;
104104
}
105105

106-
statements.push(
107-
lua.createIfStatement(
108-
conditionVariable,
109-
lua.createBlock(context.transformStatements(clause.statements))
106+
if (
107+
!(
108+
ts.isDefaultClause(clause) &&
109+
previousClause &&
110+
containsBreakOrReturn([...previousClause.statements])
110111
)
111-
);
112+
) {
113+
statements.push(
114+
lua.createIfStatement(
115+
conditionVariable,
116+
lua.createBlock(context.transformStatements(clause.statements))
117+
)
118+
);
119+
}
112120
}
113121

114122
previousClause = clause;
@@ -144,7 +152,6 @@ export const transformSwitchStatement: FunctionVisitor<ts.SwitchStatement> = (st
144152

145153
// Add the switch expression after hoisting
146154
const expression = context.transformExpression(statement.expression);
147-
statements.unshift(lua.createVariableDeclarationStatement(conditionVariable, lua.createBooleanLiteral(false)));
148155
statements.unshift(lua.createVariableDeclarationStatement(switchVariable, expression));
149156

150157
// Wrap the statements in a repeat until true statement to facilitate dynamic break/returns

test/unit/__snapshots__/switch.spec.ts.snap

Lines changed: 166 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ function ____exports.__main(self)
77
local out = {}
88
repeat
99
local ____switch3 = 5
10-
local ____cond3 = false
11-
____cond3 = ____cond3 or (((____switch3 == 0) or (____switch3 == 1)) or (____switch3 == 2))
10+
local ____cond3 = ((____switch3 == 0) or (____switch3 == 1)) or (____switch3 == 2)
1211
if ____cond3 then
1312
__TS__ArrayPush(out, \\"0,1,2\\")
1413
end
@@ -17,9 +16,6 @@ function ____exports.__main(self)
1716
__TS__ArrayPush(out, \\"3\\")
1817
break
1918
end
20-
if ____cond3 then
21-
__TS__ArrayPush(out, \\"default\\")
22-
end
2319
____cond3 = ____cond3 or (____switch3 == 4)
2420
if ____cond3 then
2521
__TS__ArrayPush(out, \\"4\\")
@@ -34,14 +30,177 @@ end
3430
return ____exports"
3531
`;
3632

33+
exports[`switch handles side-effects (0) 1`] = `
34+
"require(\\"lualib_bundle\\");
35+
local ____exports = {}
36+
function ____exports.__main(self)
37+
local out = {}
38+
local y = 0
39+
local function foo(self)
40+
return (function()
41+
local ____tmp = y
42+
y = ____tmp + 1
43+
return ____tmp
44+
end)()
45+
end
46+
local x = 0
47+
repeat
48+
local ____switch5 = x
49+
local ____cond5 = ____switch5 == foo(nil)
50+
if ____cond5 then
51+
__TS__ArrayPush(out, 1)
52+
end
53+
____cond5 = ____cond5 or (____switch5 == foo(nil))
54+
if ____cond5 then
55+
__TS__ArrayPush(out, 2)
56+
end
57+
____cond5 = ____cond5 or (____switch5 == foo(nil))
58+
if ____cond5 then
59+
__TS__ArrayPush(out, 3)
60+
end
61+
if ____cond5 then
62+
__TS__ArrayPush(out, \\"default\\")
63+
end
64+
if not ____cond5 then
65+
__TS__ArrayPush(out, \\"default\\")
66+
end
67+
until true
68+
__TS__ArrayPush(out, y)
69+
return out
70+
end
71+
return ____exports"
72+
`;
73+
74+
exports[`switch handles side-effects (1) 1`] = `
75+
"require(\\"lualib_bundle\\");
76+
local ____exports = {}
77+
function ____exports.__main(self)
78+
local out = {}
79+
local y = 0
80+
local function foo(self)
81+
return (function()
82+
local ____tmp = y
83+
y = ____tmp + 1
84+
return ____tmp
85+
end)()
86+
end
87+
local x = 1
88+
repeat
89+
local ____switch5 = x
90+
local ____cond5 = ____switch5 == foo(nil)
91+
if ____cond5 then
92+
__TS__ArrayPush(out, 1)
93+
end
94+
____cond5 = ____cond5 or (____switch5 == foo(nil))
95+
if ____cond5 then
96+
__TS__ArrayPush(out, 2)
97+
end
98+
____cond5 = ____cond5 or (____switch5 == foo(nil))
99+
if ____cond5 then
100+
__TS__ArrayPush(out, 3)
101+
end
102+
if ____cond5 then
103+
__TS__ArrayPush(out, \\"default\\")
104+
end
105+
if not ____cond5 then
106+
__TS__ArrayPush(out, \\"default\\")
107+
end
108+
until true
109+
__TS__ArrayPush(out, y)
110+
return out
111+
end
112+
return ____exports"
113+
`;
114+
115+
exports[`switch handles side-effects (2) 1`] = `
116+
"require(\\"lualib_bundle\\");
117+
local ____exports = {}
118+
function ____exports.__main(self)
119+
local out = {}
120+
local y = 0
121+
local function foo(self)
122+
return (function()
123+
local ____tmp = y
124+
y = ____tmp + 1
125+
return ____tmp
126+
end)()
127+
end
128+
local x = 2
129+
repeat
130+
local ____switch5 = x
131+
local ____cond5 = ____switch5 == foo(nil)
132+
if ____cond5 then
133+
__TS__ArrayPush(out, 1)
134+
end
135+
____cond5 = ____cond5 or (____switch5 == foo(nil))
136+
if ____cond5 then
137+
__TS__ArrayPush(out, 2)
138+
end
139+
____cond5 = ____cond5 or (____switch5 == foo(nil))
140+
if ____cond5 then
141+
__TS__ArrayPush(out, 3)
142+
end
143+
if ____cond5 then
144+
__TS__ArrayPush(out, \\"default\\")
145+
end
146+
if not ____cond5 then
147+
__TS__ArrayPush(out, \\"default\\")
148+
end
149+
until true
150+
__TS__ArrayPush(out, y)
151+
return out
152+
end
153+
return ____exports"
154+
`;
155+
156+
exports[`switch handles side-effects (3) 1`] = `
157+
"require(\\"lualib_bundle\\");
158+
local ____exports = {}
159+
function ____exports.__main(self)
160+
local out = {}
161+
local y = 0
162+
local function foo(self)
163+
return (function()
164+
local ____tmp = y
165+
y = ____tmp + 1
166+
return ____tmp
167+
end)()
168+
end
169+
local x = 3
170+
repeat
171+
local ____switch5 = x
172+
local ____cond5 = ____switch5 == foo(nil)
173+
if ____cond5 then
174+
__TS__ArrayPush(out, 1)
175+
end
176+
____cond5 = ____cond5 or (____switch5 == foo(nil))
177+
if ____cond5 then
178+
__TS__ArrayPush(out, 2)
179+
end
180+
____cond5 = ____cond5 or (____switch5 == foo(nil))
181+
if ____cond5 then
182+
__TS__ArrayPush(out, 3)
183+
end
184+
if ____cond5 then
185+
__TS__ArrayPush(out, \\"default\\")
186+
end
187+
if not ____cond5 then
188+
__TS__ArrayPush(out, \\"default\\")
189+
end
190+
until true
191+
__TS__ArrayPush(out, y)
192+
return out
193+
end
194+
return ____exports"
195+
`;
196+
37197
exports[`switch uses elseif 1`] = `
38198
"local ____exports = {}
39199
function ____exports.__main(self)
40200
local result = -1
41201
repeat
42202
local ____switch3 = 2
43-
local ____cond3 = false
44-
____cond3 = ____cond3 or (____switch3 == 0)
203+
local ____cond3 = ____switch3 == 0
45204
if ____cond3 then
46205
do
47206
result = 200

test/unit/switch.spec.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,26 +400,30 @@ test("switch collapses empty case and minimizes conditions", () => {
400400
.expectToMatchJsResult();
401401
});
402402

403-
test("switch handles side-effects", () => {
403+
test.each([0, 1, 2, 3])("switch handles side-effects (%p)", inp => {
404404
util.testFunction`
405405
const out = [];
406-
406+
407407
let y = 0;
408408
function foo() {
409409
return y++;
410410
}
411411
412-
let x = 0;
412+
let x = ${inp} as number;
413413
switch (x) {
414414
case foo():
415415
out.push(1);
416416
case foo():
417417
out.push(2);
418418
case foo():
419419
out.push(3);
420+
default:
421+
out.push("default");
420422
}
421423
422424
out.push(y);
423425
return out;
424-
`.expectToMatchJsResult();
426+
`
427+
.expectLuaToMatchSnapshot()
428+
.expectToMatchJsResult();
425429
});

0 commit comments

Comments
 (0)