Skip to content

Commit faa4896

Browse files
authored
Switch transformer (#347)
* Switch transformer * Changed incorrect version comparison to equality * Added missing =
1 parent 1ef66d1 commit faa4896

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

src/LuaTransformer.ts

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,12 +1351,67 @@ export class LuaTransformer {
13511351
);
13521352
}
13531353

1354-
public transformSwitchStatement(arg0: ts.SwitchStatement): StatementVisitResult {
1355-
throw new Error("Method not implemented.");
1354+
public transformSwitchStatement(statement: ts.SwitchStatement): StatementVisitResult {
1355+
if (this.options.luaTarget === LuaTarget.Lua51) {
1356+
throw TSTLErrors.UnsupportedForTarget("Switch statements", this.options.luaTarget, statement);
1357+
}
1358+
1359+
this.pushScope(ScopeType.Switch);
1360+
1361+
// Give the switch a unique name to prevent nested switches from acting up.
1362+
const switchName = `____TS_switch${this.scopeStack.length}`;
1363+
1364+
const expression = this.transformExpression(statement.expression);
1365+
const switchVariable = tstl.createIdentifier(switchName);
1366+
const switchVariableDeclaration = tstl.createVariableDeclarationStatement(switchVariable, expression);
1367+
1368+
const statements: tstl.Statement[] = [switchVariableDeclaration];
1369+
1370+
const caseClauses = statement.caseBlock.clauses.filter(c => ts.isCaseClause(c)) as ts.CaseClause[];
1371+
1372+
for (let i = 0; i < caseClauses.length; i++) {
1373+
const clause = caseClauses[i];
1374+
// If the clause condition holds, go to the correct label
1375+
const condition = tstl.createBinaryExpression(
1376+
switchVariable,
1377+
this.transformExpression(clause.expression),
1378+
tstl.SyntaxKind.EqualityOperator
1379+
);
1380+
const goto = tstl.createGotoStatement(`${switchName}_case_${i}`);
1381+
const conditionalGoto = tstl.createIfStatement(condition, tstl.createBlock([goto]));
1382+
statements.push(conditionalGoto);
1383+
}
1384+
1385+
const hasDefaultCase = statement.caseBlock.clauses.some(c => ts.isDefaultClause(c));
1386+
if (hasDefaultCase) {
1387+
statements.push(tstl.createGotoStatement(`${switchName}_case_default`));
1388+
} else {
1389+
statements.push(tstl.createGotoStatement(`${switchName}_end`));
1390+
}
1391+
1392+
for (let i = 0; i < statement.caseBlock.clauses.length; i++) {
1393+
const clause = statement.caseBlock.clauses[i];
1394+
const label = ts.isCaseClause(clause)
1395+
? tstl.createLabelStatement(`${switchName}_case_${i}`)
1396+
: tstl.createLabelStatement(`${switchName}_case_default`);
1397+
1398+
const body = tstl.createDoStatement(this.transformStatements(clause.statements));
1399+
statements.push(label, body);
1400+
}
1401+
1402+
statements.push(tstl.createLabelStatement(`${switchName}_end`));
1403+
1404+
this.popScope();
1405+
1406+
return statements;
13561407
}
13571408

13581409
public transformBreakStatement(breakStatement: ts.BreakStatement): StatementVisitResult {
1359-
return tstl.createBreakStatement(undefined, breakStatement);
1410+
if (this.peekScope().type === ScopeType.Switch) {
1411+
return tstl.createGotoStatement(`____TS_switch${this.scopeStack.length}_end`);
1412+
} else {
1413+
return tstl.createBreakStatement(undefined, breakStatement);
1414+
}
13601415
}
13611416

13621417
public transformTryStatement(statement: ts.TryStatement): StatementVisitResult {

test/unit/conditionals.spec.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,10 @@ export class LuaConditionalsTests {
222222
Expect(result).toBe(expected);
223223
}
224224

225-
@Test("switchLocalScope")
226225
@TestCase(0, 0)
227226
@TestCase(1, 2)
228227
@TestCase(2, 2)
228+
@Test("switchLocalScope")
229229
public switchLocalScope(inp: number, expected: number): void {
230230
const result = util.transpileAndExecute(
231231
`let result: number = -1;
@@ -253,13 +253,16 @@ export class LuaConditionalsTests {
253253
Expect(result).toBe(expected);
254254
}
255255

256-
@Test("switchReturn")
257256
@TestCase(0, 0)
258257
@TestCase(1, 1)
259258
@TestCase(2, 2)
259+
@TestCase(3, -1)
260+
@Test("switchReturn")
260261
public switchReturn(inp: number, expected: number): void {
261262
const result = util.transpileAndExecute(
262-
`switch (<number>${inp}) {
263+
`const result: number = -1;
264+
265+
switch (<number>${inp}) {
263266
case 0:
264267
return 0;
265268
break;

0 commit comments

Comments
 (0)