Skip to content

Commit 63c2e93

Browse files
authored
properly handling bitwise operators (#331)
* properly handling bitwise operators and passing original nodes in some places it wasn't being passed * Fixes and cleanup - Changed Arithmatic to Arithmetic - Throwing errors in printer in case something slips through from transformer - Throwing errors for unknown prefix/postifx unary ops - Move target-specific logic from subclasses to base transformer for bitops and unpack - Removed some unused helpers * moved bitop handling properly into transformer * broke lua52/luajit bitops out to their own functions
1 parent 34a87a1 commit 63c2e93

File tree

8 files changed

+285
-199
lines changed

8 files changed

+285
-199
lines changed

src/LuaAST.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,26 @@ export enum SyntaxKind {
7171
BitwiseOrOperator,
7272
BitwiseExclusiveOrOperator,
7373
BitwiseRightShiftOperator,
74+
BitwiseArithmeticRightShift,
7475
BitwiseLeftShiftOperator,
7576
BitwiseNotOperator, // Unary
7677
}
7778

7879
// TODO maybe name this PrefixUnary? not sure it makes sense to do so, because all unary ops in Lua are prefix
79-
export type UnaryOperator = SyntaxKind.NegationOperator | SyntaxKind.LengthOperator | SyntaxKind.NotOperator | SyntaxKind.BitwiseNotOperator;
80+
export type UnaryBitwiseOperator = SyntaxKind.BitwiseNotOperator;
81+
82+
export type UnaryOperator = SyntaxKind.NegationOperator | SyntaxKind.LengthOperator | SyntaxKind.NotOperator | UnaryBitwiseOperator;
83+
84+
export type BinaryBitwiseOperator =
85+
SyntaxKind.BitwiseAndOperator | SyntaxKind.BitwiseOrOperator | SyntaxKind.BitwiseExclusiveOrOperator |
86+
SyntaxKind.BitwiseRightShiftOperator | SyntaxKind.BitwiseArithmeticRightShift | SyntaxKind.BitwiseLeftShiftOperator;
8087

8188
export type BinaryOperator =
8289
SyntaxKind.AdditionOperator | SyntaxKind.SubractionOperator | SyntaxKind.MultiplicationOperator | SyntaxKind.DivisionOperator |
8390
SyntaxKind.FloorDivisionOperator | SyntaxKind.ModuloOperator | SyntaxKind.PowerOperator | SyntaxKind.ConcatOperator |
8491
SyntaxKind.EqualityOperator | SyntaxKind.InequalityOperator | SyntaxKind.LessThanOperator | SyntaxKind.LessEqualOperator |
8592
SyntaxKind.GreaterThanOperator | SyntaxKind.GreaterEqualOperator | SyntaxKind.AndOperator | SyntaxKind.OrOperator |
86-
SyntaxKind.BitwiseAndOperator | SyntaxKind.BitwiseOrOperator | SyntaxKind.BitwiseExclusiveOrOperator |
87-
SyntaxKind.BitwiseRightShiftOperator | SyntaxKind.BitwiseLeftShiftOperator | SyntaxKind.BitwiseNotOperator;
93+
BinaryBitwiseOperator;
8894

8995
export type Operator = UnaryOperator | BinaryOperator;
9096

src/LuaPrinter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export class LuaPrinter {
3131
[tstl.SyntaxKind.BitwiseOrOperator]: "|",
3232
[tstl.SyntaxKind.BitwiseExclusiveOrOperator]: "~",
3333
[tstl.SyntaxKind.BitwiseRightShiftOperator]: ">>",
34+
[tstl.SyntaxKind.BitwiseArithmeticRightShift]: ">>>",
3435
[tstl.SyntaxKind.BitwiseLeftShiftOperator]: "<<",
3536
[tstl.SyntaxKind.BitwiseNotOperator]: "~",
3637
};
@@ -57,7 +58,7 @@ export class LuaPrinter {
5758
|| this.options.luaLibImport === LuaLibImportKind.Always)
5859
{
5960
header += `require("lualib_bundle");\n`;
60-
}
61+
}
6162
// Inline lualib features
6263
else if (this.options.luaLibImport === LuaLibImportKind.Inline && luaLibFeatures.size > 0)
6364
{

src/LuaTransformer.ts

Lines changed: 240 additions & 54 deletions
Large diffs are not rendered by default.

src/TSHelper.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -293,30 +293,12 @@ export class TSHelper {
293293
case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken:
294294
return [true, tstl.SyntaxKind.BitwiseRightShiftOperator];
295295
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
296-
// return [true, ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken];
297-
throw new Error("Not yet implemented in lua AST"); // TODO
296+
return [true, tstl.SyntaxKind.BitwiseArithmeticRightShift];
298297
}
299298

300299
return [false, undefined];
301300
}
302301

303-
public static isCompoundPrefixUnaryOperator(node: ts.PrefixUnaryExpression): boolean {
304-
return node.operator !== ts.SyntaxKind.ExclamationToken && node.operator !== ts.SyntaxKind.MinusToken &&
305-
node.operator !== ts.SyntaxKind.PlusToken && node.operator !== ts.SyntaxKind.TildeToken;
306-
}
307-
308-
public static getUnaryCompoundAssignmentOperator(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression): ts.BinaryOperator {
309-
switch (node.operator) {
310-
case ts.SyntaxKind.PlusPlusToken:
311-
return ts.SyntaxKind.PlusToken;
312-
case ts.SyntaxKind.MinusMinusToken:
313-
return ts.SyntaxKind.MinusToken;
314-
default:
315-
throw TSTLErrors.UnsupportedKind(
316-
`unary ${ts.isPrefixUnaryExpression(node) ? "prefix" : "postfix"} operator`, node.operator, node);
317-
}
318-
}
319-
320302
public static isExpressionStatement(node: ts.Expression): boolean {
321303
return node.parent === undefined || ts.isExpressionStatement(node.parent) || ts.isForStatement(node.parent);
322304
}

src/targets/LuaTransformer.52.ts

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as ts from "typescript";
22

33
import * as tstl from "../LuaAST";
4-
import {LuaTransformer, StatementVisitResult, ScopeType} from "../LuaTransformer";
4+
import {ExpressionVisitResult, StatementVisitResult, ScopeType} from "../LuaTransformer";
55
import {TSHelper as tsHelper} from "../TSHelper";
66
import { LuaTransformer51 } from "./LuaTransformer.51";
77

@@ -31,13 +31,6 @@ export class LuaTransformer52 extends LuaTransformer51
3131
);
3232
}
3333

34-
/** @override */
35-
public createUnpackCall(expression: tstl.Expression): tstl.Expression {
36-
return tstl.createCallExpression(
37-
tstl.createTableIndexExpression(tstl.createIdentifier("table"), tstl.createStringLiteral("unpack")),
38-
[expression]);
39-
}
40-
4134
// /** @override */
4235
// public transpileBreak(node: ts.BreakStatement): string {
4336
// const topScope = this.peekSpecialScope();
@@ -49,36 +42,6 @@ export class LuaTransformer52 extends LuaTransformer51
4942
// }
5043
// }
5144

52-
// /** @override */
53-
// public transpileUnaryBitOperation(node: ts.PrefixUnaryExpression, operand: string): string {
54-
// switch (node.operator) {
55-
// case ts.SyntaxKind.TildeToken:
56-
// return `bit32.bnot(${operand})`;
57-
// default:
58-
// throw TSTLErrors.UnsupportedKind("bitwise operator", node.operator, node);
59-
// }
60-
// }
61-
62-
// /** @override */
63-
// public transpileBitOperation(node: ts.BinaryExpression, lhs: string, rhs: string): string {
64-
// switch (node.operatorToken.kind) {
65-
// case ts.SyntaxKind.AmpersandToken:
66-
// return `bit32.band(${lhs},${rhs})`;
67-
// case ts.SyntaxKind.BarToken:
68-
// return `bit32.bor(${lhs},${rhs})`;
69-
// case ts.SyntaxKind.CaretToken:
70-
// return `bit32.bxor(${lhs},${rhs})`;
71-
// case ts.SyntaxKind.LessThanLessThanToken:
72-
// return `bit32.lshift(${lhs},${rhs})`;
73-
// case ts.SyntaxKind.GreaterThanGreaterThanToken:
74-
// return `bit32.rshift(${lhs},${rhs})`;
75-
// case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
76-
// return `bit32.arshift(${lhs},${rhs})`;
77-
// default:
78-
// throw TSTLErrors.UnsupportedKind("bitwise operator", node.operatorToken.kind, node);
79-
// }
80-
// }
81-
8245
// /** @override */
8346
// public transpileSwitch(node: ts.SwitchStatement): string {
8447
// const expression = this.transpileExpression(node.expression, true);

src/targets/LuaTransformer.53.ts

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,13 @@
11
import * as ts from "typescript";
22

3-
import {LuaTransformer} from "../LuaTransformer";
3+
import * as tstl from "../LuaAST";
4+
import {ExpressionVisitResult} from "../LuaTransformer";
45
import {TSHelper as tsHelper} from "../TSHelper";
56
import { LuaTransformer52 } from "./LuaTransformer.52";
7+
import {TSTLErrors} from "../TSTLErrors";
68

79
export class LuaTransformer53 extends LuaTransformer52 {
810
// TODO
9-
// /** @override */
10-
// public transpileUnaryBitOperation(node: ts.PrefixUnaryExpression, operand: string): string {
11-
// switch (node.operator) {
12-
// case ts.SyntaxKind.TildeToken:
13-
// return `~${operand}`;
14-
// default:
15-
// throw TSTLErrors.UnsupportedKind("bitwise operator", node.operator, node);
16-
// }
17-
// }
18-
19-
// /** @override */
20-
// public transpileBitOperation(node: ts.BinaryExpression, lhs: string, rhs: string): string {
21-
// switch (node.operatorToken.kind) {
22-
// case ts.SyntaxKind.AmpersandToken:
23-
// return `${lhs} & ${rhs}`;
24-
// case ts.SyntaxKind.BarToken:
25-
// return `${lhs} | ${rhs}`;
26-
// case ts.SyntaxKind.CaretToken:
27-
// return `${lhs} ~ ${rhs}`;
28-
// case ts.SyntaxKind.LessThanLessThanToken:
29-
// return `${lhs} << ${rhs}`;
30-
// case ts.SyntaxKind.GreaterThanGreaterThanToken:
31-
// return `${lhs} >> ${rhs}`;
32-
// case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
33-
// throw TSTLErrors.UnsupportedForTarget("Bitwise >>> operator", this.options.luaTarget, node);
34-
// default:
35-
// throw TSTLErrors.UnsupportedKind("bitwise operator", node.operatorToken.kind, node);
36-
// }
37-
// }
3811

3912
// /** @override */
4013
// public getValidStringProperties(): { [js: string]: string } {

src/targets/LuaTransformer.JIT.ts

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ import {TSHelper as tsHelper} from "../TSHelper";
66
import { LuaTransformer52 } from "./LuaTransformer.52";
77

88
export class LuaTransformerJIT extends LuaTransformer52 {
9-
/** @override */
10-
public createUnpackCall(expression: tstl.Expression): tstl.Expression {
11-
return tstl.createCallExpression(tstl.createIdentifier("unpack"), [expression]);
12-
}
13-
149
// TODO
1510
// /** @override */
1611
// public transpileUnaryBitOperation(node: ts.PrefixUnaryExpression, operand: string): string {
@@ -22,26 +17,6 @@ export class LuaTransformerJIT extends LuaTransformer52 {
2217
// }
2318
// }
2419

25-
// /** @override */
26-
// public transpileBitOperation(node: ts.BinaryExpression, lhs: string, rhs: string): string {
27-
// switch (node.operatorToken.kind) {
28-
// case ts.SyntaxKind.AmpersandToken:
29-
// return `bit.band(${lhs},${rhs})`;
30-
// case ts.SyntaxKind.BarToken:
31-
// return `bit.bor(${lhs},${rhs})`;
32-
// case ts.SyntaxKind.CaretToken:
33-
// return `bit.bxor(${lhs},${rhs})`;
34-
// case ts.SyntaxKind.LessThanLessThanToken:
35-
// return `bit.lshift(${lhs},${rhs})`;
36-
// case ts.SyntaxKind.GreaterThanGreaterThanToken:
37-
// return `bit.rshift(${lhs},${rhs})`;
38-
// case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
39-
// return `bit.arshift(${lhs},${rhs})`;
40-
// default:
41-
// throw TSTLErrors.UnsupportedKind("bitwise operator", node.operatorToken.kind, node);
42-
// }
43-
// }
44-
4520
// /** @override */
4621
// public transpileDestructingAssignmentValue(node: ts.Expression): string {
4722
// return `unpack(${this.transpileExpression(node)})`;

test/unit/expressions.spec.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -113,52 +113,52 @@ export class ExpressionTests {
113113
}
114114

115115
@TestCase("~a", "bit.bnot(a);")
116-
@TestCase("a&b", "bit.band(a,b);")
117-
@TestCase("a&=b", "a = (bit.band(a,b));")
118-
@TestCase("a|b", "bit.bor(a,b);")
119-
@TestCase("a|=b", "a = (bit.bor(a,b));")
120-
@TestCase("a^b", "bit.bxor(a,b);")
121-
@TestCase("a^=b", "a = (bit.bxor(a,b));")
122-
@TestCase("a<<b", "bit.lshift(a,b);")
123-
@TestCase("a<<=b", "a = (bit.lshift(a,b));")
124-
@TestCase("a>>b", "bit.rshift(a,b);")
125-
@TestCase("a>>=b", "a = (bit.rshift(a,b));")
126-
@TestCase("a>>>b", "bit.arshift(a,b);")
127-
@TestCase("a>>>=b", "a = (bit.arshift(a,b));")
116+
@TestCase("a&b", "bit.band(a, b);")
117+
@TestCase("a&=b", "a = bit.band(a, b);")
118+
@TestCase("a|b", "bit.bor(a, b);")
119+
@TestCase("a|=b", "a = bit.bor(a, b);")
120+
@TestCase("a^b", "bit.bxor(a, b);")
121+
@TestCase("a^=b", "a = bit.bxor(a, b);")
122+
@TestCase("a<<b", "bit.lshift(a, b);")
123+
@TestCase("a<<=b", "a = bit.lshift(a, b);")
124+
@TestCase("a>>b", "bit.rshift(a, b);")
125+
@TestCase("a>>=b", "a = bit.rshift(a, b);")
126+
@TestCase("a>>>b", "bit.arshift(a, b);")
127+
@TestCase("a>>>=b", "a = bit.arshift(a, b);")
128128
@Test("Bitop [JIT]")
129129
public bitOperatorOverrideJIT(input: string, lua: string): void {
130130
Expect(util.transpileString(input, { luaTarget: LuaTarget.LuaJIT, luaLibImport: "none" })).toBe(lua);
131131
}
132132

133133
@TestCase("~a", "bit32.bnot(a);")
134-
@TestCase("a&b", "bit32.band(a,b);")
135-
@TestCase("a&=b", "a = (bit32.band(a,b));")
136-
@TestCase("a|b", "bit32.bor(a,b);")
137-
@TestCase("a|=b", "a = (bit32.bor(a,b));")
138-
@TestCase("a^b", "bit32.bxor(a,b);")
139-
@TestCase("a^=b", "a = (bit32.bxor(a,b));")
140-
@TestCase("a<<b", "bit32.lshift(a,b);")
141-
@TestCase("a<<=b", "a = (bit32.lshift(a,b));")
142-
@TestCase("a>>b", "bit32.rshift(a,b);")
143-
@TestCase("a>>=b", "a = (bit32.rshift(a,b));")
144-
@TestCase("a>>>b", "bit32.arshift(a,b);")
145-
@TestCase("a>>>=b", "a = (bit32.arshift(a,b));")
134+
@TestCase("a&b", "bit32.band(a, b);")
135+
@TestCase("a&=b", "a = bit32.band(a, b);")
136+
@TestCase("a|b", "bit32.bor(a, b);")
137+
@TestCase("a|=b", "a = bit32.bor(a, b);")
138+
@TestCase("a^b", "bit32.bxor(a, b);")
139+
@TestCase("a^=b", "a = bit32.bxor(a, b);")
140+
@TestCase("a<<b", "bit32.lshift(a, b);")
141+
@TestCase("a<<=b", "a = bit32.lshift(a, b);")
142+
@TestCase("a>>b", "bit32.rshift(a, b);")
143+
@TestCase("a>>=b", "a = bit32.rshift(a, b);")
144+
@TestCase("a>>>b", "bit32.arshift(a, b);")
145+
@TestCase("a>>>=b", "a = bit32.arshift(a, b);")
146146
@Test("Bitop [5.2]")
147147
public bitOperatorOverride52(input: string, lua: string): void {
148148
Expect(util.transpileString(input, { luaTarget: LuaTarget.Lua52, luaLibImport: "none" })).toBe(lua);
149149
}
150150

151151
@TestCase("~a", "~a;")
152152
@TestCase("a&b", "a & b;")
153-
@TestCase("a&=b", "a = (a & b);")
153+
@TestCase("a&=b", "a = a & b;")
154154
@TestCase("a|b", "a | b;")
155-
@TestCase("a|=b", "a = (a | b);")
155+
@TestCase("a|=b", "a = a | b;")
156156
@TestCase("a^b", "a ~ b;")
157-
@TestCase("a^=b", "a = (a ~ b);")
157+
@TestCase("a^=b", "a = a ~ b;")
158158
@TestCase("a<<b", "a << b;")
159-
@TestCase("a<<=b", "a = (a << b);")
159+
@TestCase("a<<=b", "a = a << b;")
160160
@TestCase("a>>b", "a >> b;")
161-
@TestCase("a>>=b", "a = (a >> b);")
161+
@TestCase("a>>=b", "a = a >> b;")
162162
@Test("Bitop [5.3]")
163163
public bitOperatorOverride53(input: string, lua: string): void {
164164
Expect(util.transpileString(input, { luaTarget: LuaTarget.Lua53, luaLibImport: "none" })).toBe(lua);

0 commit comments

Comments
 (0)