Skip to content
3 changes: 1 addition & 2 deletions src/LuaAST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ export enum SyntaxKind {
BitwiseOrOperator,
BitwiseExclusiveOrOperator,
BitwiseRightShiftOperator,
BitwiseArithmeticRightShift,
BitwiseLeftShiftOperator,
BitwiseNotOperator, // Unary
}
Expand All @@ -85,7 +84,7 @@ export type UnaryOperator = SyntaxKind.NegationOperator

export type BinaryBitwiseOperator = SyntaxKind.BitwiseAndOperator | SyntaxKind.BitwiseOrOperator
| SyntaxKind.BitwiseExclusiveOrOperator | SyntaxKind.BitwiseRightShiftOperator
| SyntaxKind.BitwiseArithmeticRightShift | SyntaxKind.BitwiseLeftShiftOperator;
| SyntaxKind.BitwiseLeftShiftOperator;

export type BinaryOperator =
SyntaxKind.AdditionOperator | SyntaxKind.SubractionOperator | SyntaxKind.MultiplicationOperator
Expand Down
1 change: 0 additions & 1 deletion src/LuaPrinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export class LuaPrinter {
[tstl.SyntaxKind.BitwiseOrOperator]: "|",
[tstl.SyntaxKind.BitwiseExclusiveOrOperator]: "~",
[tstl.SyntaxKind.BitwiseRightShiftOperator]: ">>",
[tstl.SyntaxKind.BitwiseArithmeticRightShift]: ">>>",
[tstl.SyntaxKind.BitwiseLeftShiftOperator]: "<<",
[tstl.SyntaxKind.BitwiseNotOperator]: "~",
};
Expand Down
220 changes: 121 additions & 99 deletions src/LuaTransformer.ts

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions src/TSHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,32 +262,32 @@ export class TSHelper {
return undefined;
}

public static isBinaryAssignmentToken(token: ts.SyntaxKind): [boolean, tstl.BinaryOperator] {
public static isBinaryAssignmentToken(token: ts.SyntaxKind): [boolean, ts.BinaryOperator] {
switch (token) {
case ts.SyntaxKind.BarEqualsToken:
return [true, tstl.SyntaxKind.BitwiseOrOperator];
return [true, ts.SyntaxKind.BarToken];
case ts.SyntaxKind.PlusEqualsToken:
return [true, tstl.SyntaxKind.AdditionOperator];
return [true, ts.SyntaxKind.PlusToken];
case ts.SyntaxKind.CaretEqualsToken:
return [true, tstl.SyntaxKind.BitwiseExclusiveOrOperator];
return [true, ts.SyntaxKind.CaretToken];
case ts.SyntaxKind.MinusEqualsToken:
return [true, tstl.SyntaxKind.SubractionOperator];
return [true, ts.SyntaxKind.MinusToken];
case ts.SyntaxKind.SlashEqualsToken:
return [true, tstl.SyntaxKind.DivisionOperator];
return [true, ts.SyntaxKind.SlashToken];
case ts.SyntaxKind.PercentEqualsToken:
return [true, tstl.SyntaxKind.ModuloOperator];
return [true, ts.SyntaxKind.PercentToken];
case ts.SyntaxKind.AsteriskEqualsToken:
return [true, tstl.SyntaxKind.MultiplicationOperator];
return [true, ts.SyntaxKind.AsteriskToken];
case ts.SyntaxKind.AmpersandEqualsToken:
return [true, tstl.SyntaxKind.BitwiseAndOperator];
return [true, ts.SyntaxKind.AmpersandToken];
case ts.SyntaxKind.AsteriskAsteriskEqualsToken:
return [true, tstl.SyntaxKind.PowerOperator];
return [true, ts.SyntaxKind.AsteriskAsteriskToken];
case ts.SyntaxKind.LessThanLessThanEqualsToken:
return [true, tstl.SyntaxKind.BitwiseLeftShiftOperator];
return [true, ts.SyntaxKind.LessThanLessThanToken];
case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken:
return [true, tstl.SyntaxKind.BitwiseRightShiftOperator];
return [true, ts.SyntaxKind.GreaterThanGreaterThanToken];
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
return [true, tstl.SyntaxKind.BitwiseArithmeticRightShift];
return [true, ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken];
}

return [false, undefined];
Expand Down
16 changes: 16 additions & 0 deletions test/unit/class.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,22 @@ export class ClassTests {
Expect(result).toBe("instance of b");
}

@Test("Named Class Expression")
public namedClassExpression(): void {
const result = util.transpileAndExecute(
`const a = class MyClass {
public method() {
return "foo";
}
}
let inst = new a();
return inst.method();`
);

// Assert
Expect(result).toBe("foo");
}

@Test("classExpressionBaseClassMethod")
public classExpressionBaseClassMethod(): void {
const result = util.transpileAndExecute(
Expand Down
35 changes: 20 additions & 15 deletions test/unit/expressions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { LuaTarget, LuaLibImportKind } from "../../src/CompilerOptions";

import * as ts from "typescript";
import * as util from "../src/util";
import { TSTLErrors } from "../../src/TSTLErrors";

export class ExpressionTests {

Expand Down Expand Up @@ -114,10 +115,10 @@ export class ExpressionTests {
@TestCase("a^=b", "a = bit.bxor(a, b);")
@TestCase("a<<b", "bit.lshift(a, b);")
@TestCase("a<<=b", "a = bit.lshift(a, b);")
@TestCase("a>>b", "bit.rshift(a, b);")
@TestCase("a>>=b", "a = bit.rshift(a, b);")
@TestCase("a>>>b", "bit.arshift(a, b);")
@TestCase("a>>>=b", "a = bit.arshift(a, b);")
@TestCase("a>>b", "bit.arshift(a, b);")
@TestCase("a>>=b", "a = bit.arshift(a, b);")
@TestCase("a>>>b", "bit.rshift(a, b);")
@TestCase("a>>>=b", "a = bit.rshift(a, b);")
@Test("Bitop [JIT]")
public bitOperatorOverrideJIT(input: string, lua: string): void {
const options = { luaTarget: LuaTarget.LuaJIT, luaLibImport: LuaLibImportKind.None };
Expand All @@ -133,10 +134,10 @@ export class ExpressionTests {
@TestCase("a^=b", "a = bit32.bxor(a, b);")
@TestCase("a<<b", "bit32.lshift(a, b);")
@TestCase("a<<=b", "a = bit32.lshift(a, b);")
@TestCase("a>>b", "bit32.rshift(a, b);")
@TestCase("a>>=b", "a = bit32.rshift(a, b);")
@TestCase("a>>>b", "bit32.arshift(a, b);")
@TestCase("a>>>=b", "a = bit32.arshift(a, b);")
@TestCase("a>>b", "bit32.arshift(a, b);")
@TestCase("a>>=b", "a = bit32.arshift(a, b);")
@TestCase("a>>>b", "bit32.rshift(a, b);")
@TestCase("a>>>=b", "a = bit32.rshift(a, b);")
@Test("Bitop [5.2]")
public bitOperatorOverride52(input: string, lua: string): void {
const options = { luaTarget: LuaTarget.Lua52, luaLibImport: LuaLibImportKind.None };
Expand All @@ -152,20 +153,24 @@ export class ExpressionTests {
@TestCase("a^=b", "a = a ~ b;")
@TestCase("a<<b", "a << b;")
@TestCase("a<<=b", "a = a << b;")
@TestCase("a>>b", "a >> b;")
@TestCase("a>>=b", "a = a >> b;")
@TestCase("a>>>b", "a >> b;")
@TestCase("a>>>=b", "a = a >> b;")
@Test("Bitop [5.3]")
public bitOperatorOverride53(input: string, lua: string): void {
const options = { luaTarget: LuaTarget.Lua53, luaLibImport: LuaLibImportKind.None };
Expect(util.transpileString(input, options)).toBe(lua);
}

@TestCase("a>>>b")
@TestCase("a>>>=b")
@TestCase("a>>b")
@TestCase("a>>=b")
@Test("Unsupported bitop 5.3")
public bitOperatorOverride53Unsupported(input: string): void {
Expect(() => util.transpileString(input, { luaTarget: LuaTarget.Lua53, luaLibImport: LuaLibImportKind.None }))
.toThrowError(TranspileError, "Bitwise >>> operator is/are not supported for target Lua 5.3.");
.toThrowError(TranspileError, TSTLErrors.UnsupportedKind(
"right shift operator (use >>> instead)",
ts.SyntaxKind.GreaterThanGreaterThanToken,
undefined
).message);
}

@TestCase("1+1", "1 + 1;")
Expand Down Expand Up @@ -249,7 +254,7 @@ export class ExpressionTests {
@TestCase("(inst.field + 3) & 3", (8 + 3) & 3)
@TestCase("inst.field | 3", 8 | 3)
@TestCase("inst.field << 3", 8 << 3)
@TestCase("inst.field >> 1", 8 >> 1)
@TestCase("inst.field >>> 1", 8 >> 1)
@TestCase("inst.field = 3", 3)
@TestCase(`"abc" + inst.field`, "abc8")
@Test("Get accessor expression")
Expand Down Expand Up @@ -278,7 +283,7 @@ export class ExpressionTests {
@TestCase("&= 3", (4 & 3) + 4)
@TestCase("|= 3", (4 | 3) + 4)
@TestCase("<<= 3", (4 << 3) + 4)
@TestCase(">>= 3", (4 >> 3) + 4)
@TestCase(">>>= 3", (4 >> 3) + 4)
@Test("Set accessorExpression")
public setAccessorBinary(expression: string, expected: any): void {
const source = `class MyClass {`
Expand Down
16 changes: 8 additions & 8 deletions test/unit/math.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class MathTests {
@TestCase("x &= y", "x=2;y=6")
@TestCase("x ^= y", "x=5;y=6")
@TestCase("x <<= y", "x=192;y=6")
@TestCase("x >>= y", "x=0;y=6")
@TestCase("x >>>= y", "x=0;y=6")
@Test("Operator assignment statements")
public opAssignmentStatement(statement: string, expected: string): void {
const result = util.transpileAndExecute(
Expand All @@ -76,7 +76,7 @@ export class MathTests {
@TestCase("o.p &= a[0]", "o=2;a=6")
@TestCase("o.p ^= a[0]", "o=5;a=6")
@TestCase("o.p <<= a[0]", "o=192;a=6")
@TestCase("o.p >>= a[0]", "o=0;a=6")
@TestCase("o.p >>>= a[0]", "o=0;a=6")
@Test("Operator assignment to simple property statements")
public opSimplePropAssignmentStatement(statement: string, expected: string): void {
const result = util.transpileAndExecute(
Expand All @@ -101,7 +101,7 @@ export class MathTests {
@TestCase("o.p.d &= a[0][0]", "o=2;a=[6,11],[7,13]")
@TestCase("o.p.d ^= a[0][0]", "o=5;a=[6,11],[7,13]")
@TestCase("o.p.d <<= a[0][0]", "o=192;a=[6,11],[7,13]")
@TestCase("o.p.d >>= a[0][0]", "o=0;a=[6,11],[7,13]")
@TestCase("o.p.d >>>= a[0][0]", "o=0;a=[6,11],[7,13]")
@Test("Operator assignment to deep property statements")
public opDeepPropAssignmentStatement(statement: string, expected: string): void {
const result = util.transpileAndExecute(
Expand All @@ -126,7 +126,7 @@ export class MathTests {
@TestCase("of().p &= af()[i()]", "o=2;a=6")
@TestCase("of().p ^= af()[i()]", "o=5;a=6")
@TestCase("of().p <<= af()[i()]", "o=192;a=6")
@TestCase("of().p >>= af()[i()]", "o=0;a=6")
@TestCase("of().p >>>= af()[i()]", "o=0;a=6")
@Test("Operator assignment to complex property statements")
public opComplexPropAssignmentStatement(statement: string, expected: string): void {
const result = util.transpileAndExecute(
Expand Down Expand Up @@ -154,7 +154,7 @@ export class MathTests {
@TestCase("of().p.d &= af()[i()][i()]", "o=2;a=[7,6],[11,13];i=2")
@TestCase("of().p.d ^= af()[i()][i()]", "o=5;a=[7,6],[11,13];i=2")
@TestCase("of().p.d <<= af()[i()][i()]", "o=192;a=[7,6],[11,13];i=2")
@TestCase("of().p.d >>= af()[i()][i()]", "o=0;a=[7,6],[11,13];i=2")
@TestCase("of().p.d >>>= af()[i()][i()]", "o=0;a=[7,6],[11,13];i=2")
@Test("Operator assignment to complex deep property statements")
public opComplexDeepPropAssignmentStatement(statement: string, expected: string): void {
const result = util.transpileAndExecute(
Expand Down Expand Up @@ -183,7 +183,7 @@ export class MathTests {
@TestCase("x &= y", "2;x=2;y=6")
@TestCase("x ^= y", "5;x=5;y=6")
@TestCase("x <<= y", "192;x=192;y=6")
@TestCase("x >>= y", "0;x=0;y=6")
@TestCase("x >>>= y", "0;x=0;y=6")
@TestCase("x + (y += 7)", "16;x=3;y=13")
@TestCase("x + (y += 7)", "16;x=3;y=13")
@TestCase("x++ + (y += 7)", "16;x=4;y=13")
Expand Down Expand Up @@ -211,7 +211,7 @@ export class MathTests {
@TestCase("o.p &= a[0]", "2;o=2;a=6")
@TestCase("o.p ^= a[0]", "5;o=5;a=6")
@TestCase("o.p <<= a[0]", "192;o=192;a=6")
@TestCase("o.p >>= a[0]", "0;o=0;a=6")
@TestCase("o.p >>>= a[0]", "0;o=0;a=6")
@TestCase("o.p + (a[0] += 7)", "16;o=3;a=13")
@TestCase("o.p += (a[0] += 7)", "16;o=16;a=13")
@TestCase("o.p++ + (a[0] += 7)", "16;o=4;a=13")
Expand Down Expand Up @@ -239,7 +239,7 @@ export class MathTests {
@TestCase("of().p &= af()[i()]", "2;o=2;a=6")
@TestCase("of().p ^= af()[i()]", "5;o=5;a=6")
@TestCase("of().p <<= af()[i()]", "192;o=192;a=6")
@TestCase("of().p >>= af()[i()]", "0;o=0;a=6")
@TestCase("of().p >>>= af()[i()]", "0;o=0;a=6")
@TestCase("of().p + (af()[i()] += 7)", "16;o=3;a=13")
@TestCase("of().p += (af()[i()] += 7)", "16;o=16;a=13")
@TestCase("of().p++ + (af()[i()] += 7)", "16;o=4;a=13")
Expand Down
1 change: 1 addition & 0 deletions tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"no-construct": true,
"no-debugger": true,
"no-default-export": true,
"no-duplicate-switch-case": true,
"no-duplicate-variable": true,
"no-inferrable-types": true,
"no-namespace": [true, "allow-declarations"],
Expand Down