Skip to content

Commit acd394b

Browse files
committed
Merge branch 'master' into ts-to-lua-ast
# Conflicts: # src/Compiler.ts # src/TSHelper.ts # src/Transpiler.ts # src/targets/Transpiler.JIT.ts # test/unit/assignments.spec.ts
2 parents faa4896 + e9ce425 commit acd394b

File tree

6 files changed

+100
-22
lines changed

6 files changed

+100
-22
lines changed

src/LuaLib.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ export enum LuaLibFeature {
2626
StringReplace = "StringReplace",
2727
StringSplit = "StringSplit",
2828
Symbol = "Symbol",
29-
Ternary = "Ternary",
3029
}
3130

3231
const luaLibDependencies: {[lib in LuaLibFeature]?: LuaLibFeature[]} = {

src/LuaPrinter.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ export class LuaPrinter {
360360
}
361361

362362
private needsParentheses(expression: tstl.Expression): boolean {
363-
return tstl.isBinaryExpression(expression) || tstl.isUnaryExpression(expression);
363+
return tstl.isBinaryExpression(expression) || tstl.isUnaryExpression(expression)
364+
|| tstl.isFunctionExpression(expression);
364365
}
365366

366367
private printParenthesizedExpression(expression: tstl.ParenthesizedExpression): string {
@@ -369,7 +370,9 @@ export class LuaPrinter {
369370

370371
private printCallExpression(expression: tstl.CallExpression): string {
371372
const params = expression.params ? expression.params.map(e => this.printExpression(e)).join(", ") : "";
372-
return `${this.printExpression(expression.expression)}(${params})`;
373+
return this.needsParentheses(expression.expression)
374+
? `(${this.printExpression(expression.expression)})(${params})`
375+
: `${this.printExpression(expression.expression)}(${params})`;
373376
}
374377

375378
private printMethodCallExpression(expression: tstl.MethodCallExpression): string {

src/LuaTransformer.ts

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,16 +2045,37 @@ export class LuaTransformer {
20452045
}
20462046
}
20472047

2048-
public transformConditionalExpression(node: ts.ConditionalExpression, brackets?: boolean): tstl.CallExpression {
2049-
const condition = this.transformExpression(node.condition);
2050-
const val1 = this.transformExpression(node.whenTrue);
2051-
const val2 = this.transformExpression(node.whenFalse);
2052-
2053-
return this.transformLuaLibFunction(
2054-
LuaLibFeature.Ternary,
2055-
condition,
2056-
this.wrapInFunctionCall(val1),
2057-
this.wrapInFunctionCall(val2)
2048+
public transformProtectedConditionalExpression(expression: ts.ConditionalExpression): tstl.CallExpression {
2049+
const condition = this.transformExpression(expression.condition);
2050+
const val1 = this.transformExpression(expression.whenTrue);
2051+
const val2 = this.transformExpression(expression.whenFalse);
2052+
2053+
const val1Function = this.wrapInFunctionCall(val1);
2054+
const val2Function = this.wrapInFunctionCall(val2);
2055+
2056+
// ((condition and (() => v1)) or (() => v2))()
2057+
const conditionAnd = tstl.createBinaryExpression(condition, val1Function, tstl.SyntaxKind.AndOperator);
2058+
const orExpression = tstl.createBinaryExpression(conditionAnd, val2Function, tstl.SyntaxKind.OrOperator);
2059+
return tstl.createCallExpression(orExpression, [], undefined, expression);
2060+
}
2061+
2062+
public transformConditionalExpression(expression: ts.ConditionalExpression): tstl.Expression {
2063+
const isStrict = this.options.strict || this.options.strictNullChecks;
2064+
if (tsHelper.isFalsible(this.checker.getTypeAtLocation(expression.whenTrue), isStrict)) {
2065+
return this.transformProtectedConditionalExpression(expression);
2066+
}
2067+
const condition = this.transformExpression(expression.condition);
2068+
const val1 = this.transformExpression(expression.whenTrue);
2069+
const val2 = this.transformExpression(expression.whenFalse);
2070+
2071+
// (condition and v1) or v2
2072+
const conditionAnd = tstl.createBinaryExpression(condition, val1, tstl.SyntaxKind.AndOperator);
2073+
return tstl.createBinaryExpression(
2074+
conditionAnd,
2075+
val2,
2076+
tstl.SyntaxKind.OrOperator,
2077+
undefined,
2078+
expression
20582079
);
20592080
}
20602081

src/TSHelper.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,4 +503,28 @@ export class TSHelper {
503503
public static isValidLuaIdentifier(str: string): boolean {
504504
return str.match(/[a-zA-Z_][a-zA-Z0-9_]*/) !== null;
505505
}
506+
507+
public static isFalsible(type: ts.Type, strictNullChecks: boolean): boolean {
508+
const falsibleFlags = ts.TypeFlags.Boolean
509+
| ts.TypeFlags.BooleanLiteral
510+
| ts.TypeFlags.Undefined
511+
| ts.TypeFlags.Null
512+
| ts.TypeFlags.Never
513+
| ts.TypeFlags.Void
514+
| ts.TypeFlags.Any;
515+
516+
if (type.flags & falsibleFlags) {
517+
return true;
518+
} else if (!strictNullChecks && !type.isLiteral()) {
519+
return true;
520+
} else if (type.isUnion()) {
521+
for (const subType of type.types) {
522+
if (this.isFalsible(subType, strictNullChecks)) {
523+
return true;
524+
}
525+
}
526+
}
527+
528+
return false;
529+
}
506530
}

src/lualib/Ternary.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

test/unit/expressions.spec.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Expect, Test, TestCase, FocusTests } from "alsatian";
1+
import { Expect, Test, TestCase } from "alsatian";
22
import { TranspileError } from "../../src/TranspileError";
33
import { LuaTarget } from "../../src/CompilerOptions";
44

@@ -184,6 +184,44 @@ export class ExpressionTests {
184184
Expect(util.transpileString("undefined")).toBe("nil;");
185185
}
186186

187+
@TestCase("true ? 'a' : 'b'", "a")
188+
@TestCase("false ? 'a' : 'b'", "b")
189+
@TestCase("true ? false : true", false)
190+
@TestCase("false ? false : true", true)
191+
@TestCase("true ? literalValue : true", "literal")
192+
@TestCase("true ? variableValue : true", undefined)
193+
@TestCase("true ? maybeUndefinedValue : true", undefined)
194+
@TestCase("true ? maybeBooleanValue : true", false)
195+
@TestCase("true ? maybeUndefinedValue : true", undefined, { strictNullChecks: true })
196+
@TestCase("true ? maybeBooleanValue : true", false, { strictNullChecks: true })
197+
@TestCase("true ? undefined : true", undefined, { strictNullChecks: true })
198+
@TestCase("true ? null : true", undefined, { strictNullChecks: true })
199+
@TestCase("true ? false : true", false, { luaTarget: LuaTarget.Lua51 })
200+
@TestCase("false ? false : true", true, { luaTarget: LuaTarget.Lua51 })
201+
@TestCase("true ? undefined : true", undefined, { luaTarget: LuaTarget.Lua51 })
202+
@TestCase("true ? false : true", false, { luaTarget: LuaTarget.LuaJIT })
203+
@TestCase("false ? false : true", true, { luaTarget: LuaTarget.LuaJIT })
204+
@TestCase("true ? undefined : true", undefined, { luaTarget: LuaTarget.LuaJIT })
205+
@Test("Ternary operator")
206+
public ternaryOperator(input: string, expected: any, options?: ts.CompilerOptions): void {
207+
console.log(util.transpileString(
208+
`const literalValue = 'literal';
209+
let variableValue:string;
210+
let maybeBooleanValue:string|boolean = false;
211+
let maybeUndefinedValue:string|undefined;
212+
return ${input};`, options
213+
214+
));
215+
const result = util.transpileAndExecute(
216+
`const literalValue = 'literal';
217+
let variableValue:string;
218+
let maybeBooleanValue:string|boolean = false;
219+
let maybeUndefinedValue:string|undefined;
220+
return ${input};`, options);
221+
222+
Expect(result).toBe(expected);
223+
}
224+
187225
@TestCase("inst.field", 8)
188226
@TestCase("inst.field + 3", 8 + 3)
189227
@TestCase("inst.field * 3", 8 * 3)
@@ -246,7 +284,7 @@ export class ExpressionTests {
246284
@TestCase("inst.superBaseField", 4)
247285
@Test("Inherited accessors")
248286
public inheritedAccessors(expression: string, expected: any): void {
249-
const source = `class MyBaseClass {`
287+
const source = `class MyBaseClass {`
250288
+ ` public _baseField: number;`
251289
+ ` public get baseField(): number { return this._baseField + 6; }`
252290
+ ` public set baseField(v: number) { this._baseField = v; }`

0 commit comments

Comments
 (0)