Skip to content

Commit e6440be

Browse files
committed
Numeric for statement & if statement transformer
1 parent 008eb82 commit e6440be

File tree

2 files changed

+100
-39
lines changed

2 files changed

+100
-39
lines changed

src/LuaPrinter.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,22 +115,25 @@ export class LuaPrinter {
115115
`${statement.right.map(e => this.printExpression(e)).join(", ")};\n`);
116116
}
117117

118-
private printIfStatement(statement: tstl.IfStatement): string {
119-
let result = this.indent(`if ${this.printExpression(statement.condtion)} then\n`);
118+
private printIfStatement(statement: tstl.IfStatement, isElseIf?: boolean): string {
119+
const prefix = isElseIf ? "elseif" : "if";
120+
let result = this.indent(`${prefix} ${this.printExpression(statement.condtion)} then\n`);
120121
this.pushIndent();
121122
result += this.printBlock(statement.ifBlock);
122123
this.popIndent();
123124
if (statement.elseBlock) {
124125
if (tstl.isIfStatement(statement.elseBlock)) {
125-
result += this.printIfStatement(statement.elseBlock);
126+
result += this.printIfStatement(statement.elseBlock, true);
126127
} else {
127128
result += this.indent("else\n");
128129
this.pushIndent();
129130
result += this.printBlock(statement.elseBlock);
130131
this.popIndent();
132+
result += this.indent("end\n");
131133
}
134+
} else {
135+
result += this.indent("end\n");
132136
}
133-
result += this.indent("end\n");
134137

135138
return result;
136139
}

src/LuaTransformer.ts

Lines changed: 93 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,11 @@ export class LuaTransformer {
145145
public transformStatements(
146146
statements: ts.Statement[] | ReadonlyArray<ts.Statement>): tstl.Statement[] {
147147

148-
const tstlStatements = (statements as ts.Statement[]).map(statement => this.transformStatement(statement) as tstl.Statement);
149-
150-
const flat = this.flat(tstlStatements);
151-
152-
// TODO this is somewhat hacky and not typesafe
153-
return flat;
148+
const tstlStatements: tstl.Statement[] = [];
149+
(statements as ts.Statement[]).forEach(statement => {
150+
tstlStatements.push(...this.statementVisitResultToStatementArray(this.transformStatement(statement)));
151+
});
152+
return tstlStatements;
154153
}
155154

156155
public transformBlock(block: ts.Block): tstl.Block {
@@ -850,15 +849,15 @@ export class LuaTransformer {
850849
return this.createLocalOrGlobalDeclaration(name, functionExpression, undefined, functionDeclaration);
851850
}
852851

853-
public transformTypeAliasDeclaration(arg0: ts.TypeAliasDeclaration): StatementVisitResult {
854-
throw new Error("Method not implemented.");
852+
public transformTypeAliasDeclaration(statement: ts.TypeAliasDeclaration): StatementVisitResult {
853+
return undefined;
855854
}
856855

857-
public transformInterfaceDeclaration(arg0: ts.InterfaceDeclaration): StatementVisitResult {
858-
throw new Error("Method not implemented.");
856+
public transformInterfaceDeclaration(statement: ts.InterfaceDeclaration): StatementVisitResult {
857+
return undefined;
859858
}
860859

861-
public transformVariableDeclaration(statement: ts.VariableDeclaration): StatementVisitResult {
860+
public transformVariableDeclaration(statement: ts.VariableDeclaration): tstl.Statement[] {
862861
if (statement.initializer) {
863862
// Validate assignment
864863
const initializerType = this.checker.getTypeAtLocation(statement.initializer);
@@ -878,11 +877,11 @@ export class LuaTransformer {
878877
return [tstl.createVariableDeclarationStatement(identifierName), tstl.createAssignmentStatement(identifierName, value)];
879878
} else {
880879
// local identifierName = value;
881-
return tstl.createVariableDeclarationStatement(identifierName, value);
880+
return [tstl.createVariableDeclarationStatement(identifierName, value)];
882881
}
883882
} else {
884883
// local identifierName = nil;
885-
return tstl.createVariableDeclarationStatement(identifierName, tstl.createNilLiteral());
884+
return [tstl.createVariableDeclarationStatement(identifierName, tstl.createNilLiteral())];
886885
}
887886
} else if (ts.isArrayBindingPattern(statement.name)) {
888887
// Destructuring type
@@ -897,23 +896,23 @@ export class LuaTransformer {
897896
// Don't unpack TupleReturn decorated functions
898897
if (tsHelper.isTupleReturnCall(statement.initializer, this.checker)) {
899898
// local vars = initializer;
900-
return tstl.createVariableDeclarationStatement(vars, this.transformExpression(statement.initializer));
899+
return [tstl.createVariableDeclarationStatement(vars, this.transformExpression(statement.initializer))];
901900
} else {
902901
// local vars = this.transpileDestructingAssignmentValue(node.initializer);
903-
return tstl.createVariableDeclarationStatement(vars, this.createUnpackCall(statement.initializer));
902+
return [tstl.createVariableDeclarationStatement(vars, this.createUnpackCall(statement.initializer))];
904903
}
905904
} else {
906905
throw TSTLErrors.UnsupportedKind("variable declaration", statement.name.kind, statement);
907906
}
908907
}
909908

910909
public transformVariableStatement(statement: ts.VariableStatement): StatementVisitResult {
911-
return this.flat(
912-
statement.declarationList.declarations.map(declaration => this.transformVariableDeclaration(declaration)) as tstl.Statement[]
913-
);
910+
const result: tstl.Statement[] = [];
911+
statement.declarationList.declarations.forEach(declaration => result.push(...this.transformVariableDeclaration(declaration)));
912+
return result;
914913
}
915914

916-
public transformExpressionStatement(statement: ts.ExpressionStatement | ts.Expression): StatementVisitResult {
915+
public transformExpressionStatement(statement: ts.ExpressionStatement | ts.Expression): tstl.Statement {
917916
const expression = ts.isExpressionStatement(statement) ? statement.expression : statement;
918917
if (ts.isBinaryExpression(expression)) {
919918
const [isCompound, replacementOperator] = tsHelper.isBinaryAssignmentToken(
@@ -965,7 +964,7 @@ export class LuaTransformer {
965964
return tstl.createExpressionStatement(this.transformExpression(expression));
966965
}
967966

968-
public transformReturn(statement: ts.ReturnStatement): StatementVisitResult {
967+
public transformReturn(statement: ts.ReturnStatement): tstl.Statement {
969968
if (statement.expression) {
970969
const returnType = tsHelper.getContainingFunctionReturnType(statement, this.checker);
971970
if (returnType) {
@@ -989,22 +988,58 @@ export class LuaTransformer {
989988
}
990989
}
991990

992-
public transformIfStatement(arg0: ts.IfStatement): StatementVisitResult {
993-
throw new Error("Method not implemented.");
991+
public transformIfStatement(statement: ts.IfStatement): tstl.IfStatement {
992+
const condition = this.transformExpression(statement.expression);
993+
const ifBlock = tstl.createBlock(this.statementVisitResultToStatementArray(this.transformStatement(statement.thenStatement)));
994+
if (statement.elseStatement) {
995+
if (ts.isIfStatement(statement.elseStatement)) {
996+
return tstl.createIfStatement(condition, ifBlock, this.transformIfStatement(statement.elseStatement));
997+
} else {
998+
const elseBlock = tstl.createBlock(this.statementVisitResultToStatementArray(this.transformStatement(statement.elseStatement)));
999+
return tstl.createIfStatement(condition, ifBlock, elseBlock);
1000+
}
1001+
}
1002+
return tstl.createIfStatement(condition, ifBlock);
9941003
}
9951004

996-
public transformWhileStatement(arg0: ts.WhileStatement): StatementVisitResult {
997-
throw new Error("Method not implemented.");
1005+
public transformWhileStatement(statement: ts.WhileStatement): StatementVisitResult {
1006+
return tstl.createWhileStatement(
1007+
tstl.createBlock(this.statementVisitResultToStatementArray(this.transformStatement(statement.statement))),
1008+
this.transformExpression(statement.expression)
1009+
);
9981010
}
9991011

1000-
public transformDoStatement(arg0: ts.DoStatement): StatementVisitResult {
1001-
throw new Error("Method not implemented.");
1012+
public transformDoStatement(statement: ts.DoStatement): StatementVisitResult {
1013+
return tstl.createRepeatStatement(
1014+
tstl.createBlock(this.statementVisitResultToStatementArray(this.transformStatement(statement.statement))),
1015+
tstl.createUnaryExpression(this.transformExpression(statement.expression), tstl.SyntaxKind.NotOperator)
1016+
);
10021017
}
10031018

1004-
public transformForStatement(arg0: ts.ForStatement): StatementVisitResult {
1005-
// NOTE : When implementing, make sure incrementor is transformed with transformExpressionStatement
1006-
// to ensure it is not wrapped in an iife.
1007-
throw new Error("Method not implemented.");
1019+
public transformForStatement(statement: ts.ForStatement): StatementVisitResult {
1020+
const result: tstl.Statement[] = [];
1021+
1022+
if (statement.initializer) {
1023+
for (const variableDeclaration of (statement.initializer as ts.VariableDeclarationList).declarations) {
1024+
// local initializer = value
1025+
result.push(...this.transformVariableDeclaration(variableDeclaration));
1026+
}
1027+
}
1028+
1029+
const condition = statement.condition ? this.transformExpression(statement.condition) : tstl.createBooleanLiteral(true);
1030+
1031+
// Add body
1032+
const body: tstl.Statement[] = [];
1033+
body.push(...this.statementVisitResultToStatementArray(this.transformStatement(statement.statement)));
1034+
1035+
if (statement.incrementor) {
1036+
body.push(this.transformExpressionStatement(statement.incrementor));
1037+
}
1038+
1039+
// while (condition) do ... end
1040+
result.push(tstl.createWhileStatement(tstl.createBlock(body), condition));
1041+
1042+
return result;
10081043
}
10091044

10101045
public transformForOfStatement(statement: ts.ForOfStatement): StatementVisitResult {
@@ -1079,10 +1114,12 @@ export class LuaTransformer {
10791114
undefined,
10801115
itemVariable
10811116
);
1117+
// TODO ?????
10821118
this.transformVariableDeclaration(declaration);
10831119
} else {
10841120
// Assign item variable
10851121
const assignment = ts.createAssignment(statement.initializer, itemVariable);
1122+
// TODO ??? this does nothing
10861123
this.transformExpression(assignment);
10871124
}
10881125
}
@@ -1126,7 +1163,7 @@ export class LuaTransformer {
11261163
}
11271164

11281165
public transformEmptyStatement(arg0: ts.EmptyStatement): StatementVisitResult {
1129-
throw new Error("Method not implemented.");
1166+
return undefined;
11301167
}
11311168

11321169
// Expressions
@@ -1152,6 +1189,8 @@ export class LuaTransformer {
11521189
case ts.SyntaxKind.StringLiteral:
11531190
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
11541191
return this.transformStringLiteral(expression as ts.StringLiteral);
1192+
case ts.SyntaxKind.TemplateExpression:
1193+
return this.transformTemplateExpression(expression as ts.TemplateExpression);
11551194
case ts.SyntaxKind.NumericLiteral:
11561195
return tstl.createNumericLiteral(
11571196
Number((expression as ts.NumericLiteral).text),
@@ -1468,7 +1507,7 @@ export class LuaTransformer {
14681507
lhs: ts.Expression,
14691508
rhs: ts.Expression,
14701509
replacementOperator: tstl.BinaryOperator
1471-
): StatementVisitResult {
1510+
): tstl.Statement {
14721511
const left = this.transformExpression(lhs) as tstl.IdentifierOrTableIndexExpression;
14731512
const right = this.transformExpression(rhs);
14741513

@@ -2285,6 +2324,18 @@ export class LuaTransformer {
22852324
return tstl.createStringLiteral(text);
22862325
}
22872326

2327+
public transformTemplateExpression(expression: ts.TemplateExpression): tstl.BinaryExpression {
2328+
const parts: tstl.Expression[] = [tstl.createStringLiteral(this.escapeString(expression.head.text))];
2329+
expression.templateSpans.forEach(span => {
2330+
const expr = this.transformExpression(span.expression);
2331+
const text = tstl.createStringLiteral(this.escapeString(span.literal.text));
2332+
2333+
// tostring(expr).."text"
2334+
parts.push(tstl.createBinaryExpression(tstl.createCallExpression(tstl.createIdentifier("tostring"), [expr]), text, tstl.SyntaxKind.ConcatOperator));
2335+
});
2336+
return parts.reduce((prev, current) => tstl.createBinaryExpression(prev, current, tstl.SyntaxKind.ConcatOperator)) as tstl.BinaryExpression;
2337+
}
2338+
22882339
public transformPropertyName(propertyName: ts.PropertyName): ExpressionVisitResult {
22892340
if (ts.isComputedPropertyName(propertyName)) {
22902341
return this.transformExpression(propertyName.expression);
@@ -2520,18 +2571,25 @@ export class LuaTransformer {
25202571
return this.scopeStack.pop();
25212572
}
25222573

2523-
private flat<T>(arr: T[] | ReadonlyArray<T>): T[] {
2574+
private statementVisitResultToStatementArray(visitResult: StatementVisitResult): tstl.Statement[] {
2575+
if (!Array.isArray(visitResult)) {
2576+
if (visitResult) {
2577+
return [visitResult];
2578+
}
2579+
return [];
2580+
}
25242581
const flatten = (arr, result = []) => {
25252582
for (let i = 0, length = arr.length; i < length; i++) {
25262583
const value = arr[i];
25272584
if (Array.isArray(value)) {
25282585
flatten(value, result);
2529-
} else {
2586+
} else if (value) {
2587+
// ignore value if undefined
25302588
result.push(value);
25312589
}
25322590
}
25332591
return result;
25342592
};
2535-
return flatten(arr);
2593+
return flatten(visitResult);
25362594
}
25372595
}

0 commit comments

Comments
 (0)