Skip to content

Commit 1e51d6f

Browse files
authored
Version split (#117)
* Intial Split * Redeclared LuaTranspiler as abstract * Moved version specific string functions * Improved error message for string properties * Changed inheritance & fixed tests
1 parent 7f39d57 commit 1e51d6f

File tree

8 files changed

+214
-147
lines changed

8 files changed

+214
-147
lines changed

src/Compiler.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@ import * as path from "path";
55
import * as ts from "typescript";
66

77
import { CompilerOptions, parseCommandLine } from "./CommandLineParser";
8-
import { LuaTranspiler, TranspileError } from "./Transpiler";
8+
import { LuaTranspiler51 } from "./targets/Transpiler.51";
9+
import { LuaTranspiler52 } from "./targets/Transpiler.52";
10+
import { LuaTranspiler53 } from "./targets/Transpiler.53";
11+
import { LuaTranspilerJIT } from "./targets/Transpiler.JIT";
12+
import { LuaTarget, LuaTranspiler, TranspileError } from "./Transpiler";
913
import { TSHelper as tsEx } from "./TSHelper";
1014

1115
export function compile(fileNames: string[], options: CompilerOptions): void {
16+
if (!options.luaTarget) {
17+
options.luaTarget = LuaTarget.LuaJIT;
18+
}
19+
1220
const program = ts.createProgram(fileNames, options);
1321
const checker = program.getTypeChecker();
1422

@@ -41,7 +49,7 @@ export function compile(fileNames: string[], options: CompilerOptions): void {
4149
const rootDir = options.rootDir;
4250

4351
// Transpile AST
44-
const lua = LuaTranspiler.transpileSourceFile(sourceFile, checker, options);
52+
const lua = createTranspiler(checker, options, sourceFile).transpileSourceFile();
4553

4654
let outPath = sourceFile.fileName;
4755
if (options.outDir !== options.rootDir) {
@@ -90,6 +98,31 @@ export function compile(fileNames: string[], options: CompilerOptions): void {
9098
);
9199
}
92100

101+
export function createTranspiler(checker: ts.TypeChecker,
102+
options: ts.CompilerOptions,
103+
sourceFile: ts.SourceFile): LuaTranspiler {
104+
let luaTargetTranspiler: LuaTranspiler;
105+
switch (options.luaTarget) {
106+
case LuaTarget.LuaJIT:
107+
luaTargetTranspiler = new LuaTranspilerJIT(checker, options, sourceFile);
108+
break;
109+
case LuaTarget.Lua51:
110+
luaTargetTranspiler = new LuaTranspiler51(checker, options, sourceFile);
111+
break;
112+
case LuaTarget.Lua52:
113+
luaTargetTranspiler = new LuaTranspiler52(checker, options, sourceFile);
114+
break;
115+
case LuaTarget.Lua53:
116+
luaTargetTranspiler = new LuaTranspiler53(checker, options, sourceFile);
117+
break;
118+
default:
119+
// should not happen
120+
throw Error("No luaTarget Specified please ensure a target is set!");
121+
}
122+
123+
return luaTargetTranspiler;
124+
}
125+
93126
export function execCommandLine(argv?: string[]) {
94127
argv = argv ? argv : process.argv.slice(2);
95128
const commandLine = parseCommandLine(argv);

src/Transpiler.ts

Lines changed: 51 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -18,40 +18,15 @@ export class TranspileError extends Error {
1818
}
1919

2020
export enum LuaTarget {
21+
Lua51 = "5.1",
22+
Lua52 = "5.2",
2123
Lua53 = "5.3",
2224
LuaJIT = "JIT",
2325
}
2426

25-
export class LuaTranspiler {
27+
export abstract class LuaTranspiler {
2628
public static AvailableLuaTargets = [LuaTarget.LuaJIT, LuaTarget.Lua53];
2729

28-
// Transpile a source file
29-
public static transpileSourceFile(node: ts.SourceFile,
30-
checker: ts.TypeChecker,
31-
options: CompilerOptions): string {
32-
const transpiler = new LuaTranspiler(checker, options, node);
33-
34-
let header = "";
35-
if (options.addHeader) {
36-
header = "-- Generated by TypescriptToLua v" + packageJSON.version + "\n" +
37-
"-- https://github.com/Perryvw/TypescriptToLua\n";
38-
}
39-
let result = header;
40-
if (!options.dontRequireLuaLib) {
41-
// require helper functions
42-
result += `require("typescript_lualib")\n`;
43-
}
44-
if (transpiler.isModule) {
45-
// Shadow exports if it already exists
46-
result += "local exports = exports or {}\n";
47-
}
48-
result += transpiler.transpileBlock(node);
49-
if (transpiler.isModule) {
50-
result += "return exports\n";
51-
}
52-
return result;
53-
}
54-
5530
public indent: string;
5631
public checker: ts.TypeChecker;
5732
public options: ts.CompilerOptions;
@@ -130,6 +105,29 @@ export class LuaTranspiler {
130105
return `"${relativePath.replace(new RegExp("\\\\|\/", "g"), ".")}"`;
131106
}
132107

108+
// Transpile a source file
109+
public transpileSourceFile(): string {
110+
let header = "";
111+
if (this.options.addHeader) {
112+
header = "-- Generated by TypescriptToLua v" + packageJSON.version + "\n" +
113+
"-- https://github.com/Perryvw/TypescriptToLua\n";
114+
}
115+
let result = header;
116+
if (!this.options.dontRequireLuaLib) {
117+
// require helper functions
118+
result += `require("typescript_lualib")\n`;
119+
}
120+
if (this.isModule) {
121+
// Shadow exports if it already exists
122+
result += "local exports = exports or {}\n";
123+
}
124+
result += this.transpileBlock(this.sourceFile);
125+
if (this.isModule) {
126+
result += "return exports\n";
127+
}
128+
return result;
129+
}
130+
133131
// Transpile a block
134132
public transpileBlock(node: ts.Node): string {
135133
let result = "";
@@ -655,102 +653,18 @@ export class LuaTranspiler {
655653
let result = "";
656654

657655
// Transpile Bitops
658-
if (this.options.luaTarget === LuaTarget.LuaJIT) {
659-
switch (node.operatorToken.kind) {
660-
case ts.SyntaxKind.AmpersandToken:
661-
result = `bit.band(${lhs},${rhs})`;
662-
break;
663-
case ts.SyntaxKind.AmpersandEqualsToken:
664-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
665-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression,
666-
`bit.band(${lhs},${rhs})`);
667-
}
668-
result = `${lhs}=bit.band(${lhs},${rhs})`;
669-
break;
670-
case ts.SyntaxKind.BarToken:
671-
result = `bit.bor(${lhs},${rhs})`;
672-
break;
673-
case ts.SyntaxKind.BarEqualsToken:
674-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
675-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression,
676-
`bit.bor(${lhs},${rhs})`);
677-
}
678-
result = `${lhs}=bit.bor(${lhs},${rhs})`;
679-
break;
680-
case ts.SyntaxKind.LessThanLessThanToken:
681-
result = `bit.lshift(${lhs},${rhs})`;
682-
break;
683-
case ts.SyntaxKind.LessThanLessThanEqualsToken:
684-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
685-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression,
686-
`bit.lshift(${lhs},${rhs})`);
687-
}
688-
result = `${lhs}=bit.lshift(${lhs},${rhs})`;
689-
break;
690-
case ts.SyntaxKind.GreaterThanGreaterThanToken:
691-
result = `bit.arshift(${lhs},${rhs})`;
692-
break;
693-
case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken:
694-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
695-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression,
696-
`bit.arshift(${lhs},${rhs})`);
697-
}
698-
result = `${lhs}=bit.arshift(${lhs},${rhs})`;
699-
break;
700-
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
701-
result = `bit.rshift(${lhs},${rhs})`;
702-
break;
703-
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
704-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
705-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression,
706-
`bit.rshift(${lhs},${rhs})`);
707-
}
708-
result = `${lhs}=bit.rshift(${lhs},${rhs})`;
709-
break;
710-
}
711-
} else {
712-
switch (node.operatorToken.kind) {
713-
case ts.SyntaxKind.AmpersandToken:
714-
result = `${lhs}&${rhs}`;
715-
break;
716-
case ts.SyntaxKind.AmpersandEqualsToken:
717-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
718-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression, `${lhs}&${rhs}`);
719-
}
720-
result = `${lhs}=${lhs}&${rhs}`;
721-
break;
722-
case ts.SyntaxKind.BarToken:
723-
result = `${lhs}|${rhs}`;
724-
break;
725-
case ts.SyntaxKind.BarEqualsToken:
726-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
727-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression, `${lhs}|${rhs}`);
728-
}
729-
result = `${lhs}=${lhs}|${rhs}`;
730-
break;
731-
case ts.SyntaxKind.LessThanLessThanToken:
732-
result = `${lhs}<<${rhs}`;
733-
break;
734-
case ts.SyntaxKind.LessThanLessThanEqualsToken:
735-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
736-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression, `${lhs}<<${rhs}`);
737-
}
738-
result = `${lhs}=${lhs}<<${rhs}`;
739-
break;
740-
case ts.SyntaxKind.GreaterThanGreaterThanToken:
741-
result = `${lhs}>>${rhs}`;
742-
break;
743-
case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken:
744-
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
745-
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression, `${lhs}>>${rhs}`);
746-
}
747-
result = `${lhs}=${lhs}>>${rhs}`;
748-
break;
749-
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
750-
throw new TranspileError("Bitwise operator >>> not supported", node);
751-
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
752-
throw new TranspileError("Bitwise operator >>> not supported", node);
753-
}
656+
switch (node.operatorToken.kind) {
657+
case ts.SyntaxKind.AmpersandToken:
658+
case ts.SyntaxKind.AmpersandEqualsToken:
659+
case ts.SyntaxKind.BarToken:
660+
case ts.SyntaxKind.BarEqualsToken:
661+
case ts.SyntaxKind.LessThanLessThanToken:
662+
case ts.SyntaxKind.LessThanLessThanEqualsToken:
663+
case ts.SyntaxKind.GreaterThanGreaterThanToken:
664+
case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken:
665+
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
666+
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
667+
result = this.transpileBitOperation(node, lhs, rhs);
754668
}
755669

756670
// Transpile operators
@@ -862,6 +776,10 @@ export class LuaTranspiler {
862776
}
863777
}
864778

779+
public transpileBitOperation(node: ts.BinaryExpression, lhs: string, rhs: string): string {
780+
throw new TranspileError(`Bit Oeprations are not supported in Lua ${this.options.target}`, node);
781+
}
782+
865783
public transpileTemplateExpression(node: ts.TemplateExpression) {
866784
const parts = [`"${node.head.text}"`];
867785
node.templateSpans.forEach(span => {
@@ -1015,24 +933,22 @@ export class LuaTranspiler {
1015933
}
1016934
}
1017935

1018-
// Transpile a String._ property
1019-
public transpileStringExpression(identifier: ts.Identifier): string {
1020-
const translation = {
936+
public getValidStringProperties(): {[js: string]: string} {
937+
return {
1021938
fromCharCode: "string.char",
1022-
fromCodePoint: "utf8.char",
1023939
};
940+
}
1024941

1025-
if (identifier.escapedText as string === "fromCodePoint" && this.options.luaTarget !== LuaTarget.Lua53) {
1026-
throw new TranspileError(
1027-
`Unsupported string property ${identifier.escapedText} is only supported for lua 5.3.`,
1028-
identifier
1029-
);
1030-
}
942+
// Transpile a String._ property
943+
public transpileStringExpression(identifier: ts.Identifier): string {
944+
const translation = this.getValidStringProperties();
1031945

1032946
if (translation[identifier.escapedText as string]) {
1033947
return `${translation[identifier.escapedText as string]}`;
1034948
} else {
1035-
throw new TranspileError(`Unsupported string property ${identifier.escapedText}.`, identifier);
949+
throw new TranspileError(`Unsupported string property ${identifier.escapedText}, ` +
950+
`is not supported in Lua ${this.options.luaTarget}.`,
951+
identifier);
1036952
}
1037953
}
1038954

src/targets/Transpiler.51.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { LuaTranspiler, TranspileError } from "../Transpiler";
2+
import { TSHelper as tsHelper } from "../TSHelper";
3+
4+
import * as ts from "typescript";
5+
6+
export class LuaTranspiler51 extends LuaTranspiler {
7+
}

src/targets/Transpiler.52.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { TSHelper as tsHelper } from "../TSHelper";
2+
import { LuaTranspiler51 } from "./Transpiler.51";
3+
4+
import * as ts from "typescript";
5+
6+
export class LuaTranspiler52 extends LuaTranspiler51 {
7+
8+
}

src/targets/Transpiler.53.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { TranspileError } from "../Transpiler";
2+
import { TSHelper as tsHelper } from "../TSHelper";
3+
import { LuaTranspiler52 } from "./Transpiler.52";
4+
5+
import * as ts from "typescript";
6+
7+
export class LuaTranspiler53 extends LuaTranspiler52 {
8+
public transpileBitOperation(node: ts.BinaryExpression, lhs: string, rhs: string): string {
9+
switch (node.operatorToken.kind) {
10+
case ts.SyntaxKind.AmpersandToken:
11+
return `${lhs}&${rhs}`;
12+
case ts.SyntaxKind.AmpersandEqualsToken:
13+
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
14+
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression, `${lhs}&${rhs}`);
15+
}
16+
return `${lhs}=${lhs}&${rhs}`;
17+
case ts.SyntaxKind.BarToken:
18+
return `${lhs}|${rhs}`;
19+
case ts.SyntaxKind.BarEqualsToken:
20+
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
21+
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression, `${lhs}|${rhs}`);
22+
}
23+
return `${lhs}=${lhs}|${rhs}`;
24+
case ts.SyntaxKind.LessThanLessThanToken:
25+
return `${lhs}<<${rhs}`;
26+
case ts.SyntaxKind.LessThanLessThanEqualsToken:
27+
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
28+
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression, `${lhs}<<${rhs}`);
29+
}
30+
return `${lhs}=${lhs}<<${rhs}`;
31+
case ts.SyntaxKind.GreaterThanGreaterThanToken:
32+
return `${lhs}>>${rhs}`;
33+
case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken:
34+
if (tsHelper.hasSetAccessor(node.left, this.checker)) {
35+
return this.transpileSetAccessor(node.left as ts.PropertyAccessExpression, `${lhs}>>${rhs}`);
36+
}
37+
return `${lhs}=${lhs}>>${rhs}`;
38+
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
39+
throw new TranspileError("Bitwise operator >>> not supported in Lua 5.3", node);
40+
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
41+
throw new TranspileError("Bitwise operator >>> not supported in Lua 5.3", node);
42+
}
43+
}
44+
public getValidStringProperties(): {[js: string]: string} {
45+
return {
46+
fromCharCode: "string.char",
47+
fromCodePoint: "utf8.char",
48+
};
49+
}
50+
51+
}

0 commit comments

Comments
 (0)