Skip to content

Commit 37ea1a6

Browse files
committed
If statements and while loops
1 parent b73cf9d commit 37ea1a6

2 files changed

Lines changed: 82 additions & 55 deletions

File tree

Transpiler.ts

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,64 @@ export class LuaTranspiler {
4343
return indent + this.transpileExpression(<ts.Expression>tsEx.getChildren(node)[0]) + "\n";
4444
case ts.SyntaxKind.ReturnStatement:
4545
return indent + this.transpileReturn(<ts.ReturnStatement>node) + "\n";
46+
case ts.SyntaxKind.IfStatement:
47+
return this.transpileIf(<ts.IfStatement>node, indent);
48+
case ts.SyntaxKind.WhileStatement:
49+
return this.transpileWhile(<ts.WhileStatement>node, indent);
4650
case ts.SyntaxKind.ForStatement:
4751
return this.transpileFor(<ts.ForStatement>node, indent);
4852
case ts.SyntaxKind.ForOfStatement:
4953
return this.transpileForOf(<ts.ForOfStatement>node, indent);
5054
case ts.SyntaxKind.ForInStatement:
5155
return this.transpileForIn(<ts.ForInStatement>node, indent);
56+
case ts.SyntaxKind.BreakStatement:
57+
return indent + "break\n";
58+
case ts.SyntaxKind.ContinueKeyword:
59+
// Disallow continue
60+
throw new TranspileError("Continue is not supported in Lua", node);
5261
case ts.SyntaxKind.EndOfFileToken:
5362
return "";
5463
default:
5564
throw new TranspileError("Unsupported node kind: " + tsEx.enumName(node.kind, ts.SyntaxKind), node);
5665
}
5766
}
5867

59-
static transpileFor(node: ts.ForStatement, indent: string): string {
68+
static transpileIf(node: ts.IfStatement, indent: string): string {
69+
const condition = this.transpileExpression(node.expression);
70+
71+
let result = indent + `if ${condition} then\n`;
72+
result += this.transpileBlock(node.thenStatement, indent + " ");
73+
74+
if (node.elseStatement) {
75+
result += indent + "else\n";
76+
result += this.transpileBlock(node.elseStatement, indent + " ");
77+
}
6078

61-
// Get identifier
62-
const identifier = tsEx.getFirstChildOfType<ts.Identifier>(tsEx.getChildren(node.initializer)[0], ts.isIdentifier);
79+
return result + indent + "end\n";
80+
}
6381

82+
static transpileWhile(node: ts.WhileStatement, indent: string): string {
83+
const condition = this.transpileExpression(node.expression);
84+
85+
let result = indent + `while ${condition} do\n`;
86+
result += this.transpileBlock(node.statement, indent + " ");
87+
return result + indent + "end\n";
88+
}
89+
90+
static transpileFor(node: ts.ForStatement, indent: string): string {
91+
// Goal: Populate three for components:
6492
let start = "0";
6593
let end = "0";
6694
let step = "1";
6795

96+
// Get variable
97+
const variable = (<ts.VariableDeclarationList>node.initializer).declarations[0];
98+
const identifier = <ts.Identifier>variable.name;
99+
68100
// Get initial value
69-
const varDec = tsEx.getFirstChildOfType<ts.VariableDeclaration>(node.initializer, ts.isVariableDeclaration);
70-
start = this.transpileExpression(tsEx.getChildren(varDec)[1]);
101+
start = this.transpileExpression(variable.initializer);
71102

103+
// Get ending value
72104
if (ts.isBinaryExpression(node.condition)) {
73105
if (ts.isIdentifier(node.condition.left)) {
74106
// Account for lua 1 indexing
@@ -153,7 +185,7 @@ export class LuaTranspiler {
153185

154186
static transpileForOf(node: ts.ForOfStatement, indent: string): string {
155187
// Get variable identifier
156-
const variable = <ts.VariableDeclaration>(<ts.VariableDeclarationList>node.initializer).declarations[0];
188+
const variable = (<ts.VariableDeclarationList>node.initializer).declarations[0];
157189
const identifier = <ts.Identifier>variable.name;
158190

159191
// Transpile expression
@@ -197,6 +229,8 @@ export class LuaTranspiler {
197229
return this.transpileCallExpression(<ts.CallExpression>node);
198230
case ts.SyntaxKind.PropertyAccessExpression:
199231
return this.transpilePropertyAccessExpression(<ts.PropertyAccessExpression>node);
232+
case ts.SyntaxKind.ElementAccessExpression:
233+
return this.transpileElementAccessExpression(<ts.ElementAccessExpression>node);
200234
case ts.SyntaxKind.Identifier:
201235
// For identifiers simply return their name
202236
return (<ts.Identifier>node).text;
@@ -214,11 +248,11 @@ export class LuaTranspiler {
214248
case ts.SyntaxKind.PrefixUnaryExpression:
215249
return this.transpilePrefixUnaryExpression(<ts.PrefixUnaryExpression>node);
216250
case ts.SyntaxKind.ArrayLiteralExpression:
217-
return this.transpileArrayLiteral(node);
251+
return this.transpileArrayLiteral(<ts.ArrayLiteralExpression>node);
218252
case ts.SyntaxKind.ObjectLiteralExpression:
219-
return this.transpileObjectLiteral(node);
253+
return this.transpileObjectLiteral(<ts.ObjectLiteralExpression>node);
220254
case ts.SyntaxKind.FunctionExpression:
221-
return this.transpileFunctionExpression(node);
255+
return this.transpileFunctionExpression(<ts.FunctionExpression>node);
222256
default:
223257
throw new TranspileError("Unsupported expression kind: " + tsEx.enumName(node.kind, ts.SyntaxKind), node);
224258
}
@@ -287,16 +321,14 @@ export class LuaTranspiler {
287321
}
288322

289323
static transpileCallExpression(node: ts.CallExpression): string {
290-
const children = tsEx.getChildren(node);
291-
292-
let callPath = this.transpileExpression(children[0]);
324+
let callPath = this.transpileExpression(node.expression);
293325
// Remove last . with :
294326
if (callPath.indexOf(".") > -1) {
295327
callPath = callPath.substr(0, callPath.lastIndexOf(".")) + ":" + callPath.substr(callPath.lastIndexOf(".") + 1);
296328
}
297329

298330
const parameters = [];
299-
children.slice(1).forEach(param => {
331+
node.arguments.forEach(param => {
300332
parameters.push(this.transpileExpression(param));
301333
})
302334

@@ -326,12 +358,18 @@ export class LuaTranspiler {
326358
return parts.join(".");
327359
}
328360

361+
static transpileElementAccessExpression(node: ts.ElementAccessExpression): string {
362+
const element = this.transpileExpression(node.expression);
363+
const index = this.transpileExpression(node.argumentExpression);
364+
365+
return `${element}[${index}]`;
366+
}
367+
329368
// Transpile a variable statement
330369
static transpileVariableStatement(node: ts.VariableStatement): string {
331370
let result = "";
332371

333-
let list = tsEx.getFirstChildOfType<ts.VariableDeclarationList>(node, ts.isVariableDeclarationList);
334-
list.declarations.forEach(declaration => {
372+
node.declarationList.declarations.forEach(declaration => {
335373
result += this.transpileVariableDeclaration(<ts.VariableDeclaration>declaration);
336374
});
337375

@@ -340,10 +378,8 @@ export class LuaTranspiler {
340378

341379
static transpileVariableDeclaration(node: ts.VariableDeclaration): string {
342380
// Find variable identifier
343-
const identifier = tsEx.getFirstChildOfType<ts.Identifier>(node, ts.isIdentifier);
344-
const valueLiteral = tsEx.getChildren(node)[1];
345-
346-
const value = this.transpileExpression(valueLiteral);
381+
const identifier = <ts.Identifier>node.name;
382+
const value = this.transpileExpression(node.initializer);
347383

348384
return `local ${identifier.escapedText} = ${value}`;
349385
}
@@ -358,7 +394,7 @@ export class LuaTranspiler {
358394
// Build parameter string
359395
let paramNames = [];
360396
parameters.forEach(param => {
361-
paramNames.push(tsEx.getFirstChildOfType<ts.Identifier>(param, ts.isIdentifier).escapedText);
397+
paramNames.push((<ts.Identifier>param.name).escapedText);
362398
});
363399

364400
// Build function header
@@ -374,12 +410,8 @@ export class LuaTranspiler {
374410

375411
// Transpile a class declaration
376412
static transpileClass(node: ts.ClassDeclaration, indent: string): string {
377-
378-
// Find first identifier
379-
const identifierNode = tsEx.getFirstChildOfType<ts.Identifier>(node, child => ts.isIdentifier(child));
380-
381413
// Write class declaration
382-
const className = <string>identifierNode.escapedText;
414+
const className = <string>node.name.escapedText;
383415
let result = indent + `${className} = ${className} or {}\n`;
384416

385417
// Get all properties
@@ -396,8 +428,8 @@ export class LuaTranspiler {
396428
// Find value assignment
397429
const assignments = tsEx.getChildrenOfType(p, tsEx.isValueType);
398430

399-
// [0] is name literal, [1] is value, ignore fields with no assigned value
400-
if (assignments.length < 2)
431+
// Ignore fields with no assigned value
432+
if (!p.initializer)
401433
continue;
402434

403435
if (isStatic) {
@@ -449,38 +481,34 @@ export class LuaTranspiler {
449481
// Add in instance field declarations
450482
for (const f of instanceFields) {
451483
// Get identifier
452-
const fieldIdentifier = tsEx.getFirstChildOfType<ts.Identifier>(f, ts.isIdentifier);
484+
const fieldIdentifier = <ts.Identifier>f.name;
453485
const fieldName = fieldIdentifier.escapedText;
454486

455-
// Get value at index 1 (index 0 is field name)
456-
const valueNode = tsEx.getChildrenOfType<ts.Node>(f, tsEx.isValueType)[1];
457-
let value = this.transpileExpression(valueNode);
487+
let value = this.transpileExpression(f.initializer);
458488

459489
result += indent + ` self.${fieldName} = ${value}\n`;
460490
}
461491

462492
// Transpile constructor body
463-
tsEx.getChildrenOfType<ts.Block>(node, ts.isBlock).forEach(child => {
464-
result += this.transpileBlock(child, indent + " ");
465-
});
493+
result += this.transpileBlock(node.body, indent + " ");
466494

467495
return result + `${indent}end\n`;
468496
}
469497

470-
static transpileArrayLiteral(node: ts.Node): string {
498+
static transpileArrayLiteral(node: ts.ArrayLiteralExpression): string {
471499
let values = [];
472500

473-
node.forEachChild(child => {
501+
node.elements.forEach(child => {
474502
values.push(this.transpileExpression(child));
475503
});
476504

477505
return "{" + values.join(",") + "}";
478506
}
479507

480-
static transpileObjectLiteral(node: ts.Node): string {
508+
static transpileObjectLiteral(node: ts.ObjectLiteralExpression): string {
481509
let properties = [];
482510
// Add all property assignments
483-
tsEx.getChildrenOfType<ts.PropertyAssignment>(node, ts.isPropertyAssignment).forEach(assignment => {
511+
node.properties.forEach(assignment => {
484512
const [key, value] = tsEx.getChildren(assignment);
485513
if (ts.isIdentifier(key)) {
486514
properties.push(`["${key.escapedText}"]=`+this.transpileExpression(value));
@@ -493,16 +521,13 @@ export class LuaTranspiler {
493521
return "{" + properties.join(",") + "}";
494522
}
495523

496-
static transpileFunctionExpression(node: ts.Node): string {
497-
let params = tsEx.getChildrenOfType<ts.ParameterDeclaration>(node, ts.isParameter);
524+
static transpileFunctionExpression(node: ts.FunctionExpression): string {
498525
// Build parameter string
499526
let paramNames = [];
500-
params.forEach(param => {
527+
node.parameters.forEach(param => {
501528
paramNames.push(tsEx.getFirstChildOfType<ts.Identifier>(param, ts.isIdentifier).escapedText);
502529
});
503530

504-
let block = tsEx.getFirstChildOfType<ts.Block>(node, ts.isBlock);
505-
506-
return `function(${paramNames.join(",")})\n` + this.transpileBlock(block, " ")+ " end\n";
531+
return `function(${paramNames.join(",")})\n` + this.transpileBlock(node.body, " ")+ " end\n";
507532
}
508533
}

test/test2.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ declare interface unit {
1414
declare function GetUnit(): unit;
1515

1616
class TestClass {
17-
static field2: number = 5;
18-
field: string = "a";
17+
static field2: number;
18+
field: string;
1919
field3: string = globalString; // Abc
2020
unit: unit;
2121

@@ -61,17 +61,19 @@ function Activate() {
6161
let a = 24 & 4;
6262

6363
let list = [1,2,3];
64-
65-
for (let i of list) {
66-
print(i);
64+
for (let i = 0; i < list.length; i++) {
65+
print(list[i]);
6766
}
6867

69-
for (let i of [1,2,3]) {
70-
print(i);
71-
print(i+1);
68+
if (i == 3 && i < 3) {
69+
print(4);
70+
} else {
71+
print(5);
7272
}
7373

74-
for (let i in [1,2,3]) {
75-
76-
}
74+
if (true || false) {
75+
while (true) {
76+
break;
77+
}
78+
}
7779
}

0 commit comments

Comments
 (0)