Skip to content

Commit f390622

Browse files
committed
refactor(lualib): move 5.0-specific to its own directory
1 parent fdcea36 commit f390622

20 files changed

+263
-33
lines changed

src/lualib-build/plugin.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ class LuaLibPlugin implements tstl.Plugin {
4242
emitBOM
4343
);
4444

45+
// Flatten the output folder structure; we do not want to keep the target-specific directories
46+
for (const file of result) {
47+
let outPath = file.fileName;
48+
while (outPath.includes("lualib") && path.basename(path.dirname(outPath)) !== "lualib") {
49+
const upOne = path.join(path.dirname(outPath), "..", path.basename(outPath));
50+
outPath = path.normalize(upOne);
51+
}
52+
file.fileName = outPath;
53+
}
54+
4555
// Create map of result files keyed by their 'lualib name'
4656
const exportedLualibFeatures = new Map(result.map(f => [path.basename(f.fileName).split(".")[0], f.code]));
4757

src/lualib/5.0/CountVarargs.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/** @noSelfInFile */
2+
3+
export function __TS__CountVarargs<T>(...args: T[]): number {
4+
// select() is not available in Lua 5.0. In this version, the arg table
5+
// includes trailing nils.
6+
return args.length;
7+
}

src/lualib/5.0/Error.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
interface ErrorType {
2+
name: string;
3+
new (...args: any[]): Error;
4+
}
5+
6+
function getErrorStack(constructor: () => any): string {
7+
let level = 1;
8+
while (true) {
9+
const info = debug.getinfo(level, "f");
10+
level += 1;
11+
if (!info) {
12+
// constructor is not in call stack
13+
level = 1;
14+
break;
15+
} else if (info.func === constructor) {
16+
break;
17+
}
18+
}
19+
20+
return debug.traceback(`[Level ${level}]`);
21+
}
22+
23+
function wrapErrorToString<T extends Error>(getDescription: (this: T) => string): (this: T) => string {
24+
return function (this: Error): string {
25+
const description = getDescription.call(this);
26+
return description;
27+
};
28+
}
29+
30+
function initErrorClass(Type: ErrorType, name: string): any {
31+
Type.name = name;
32+
return setmetatable(Type, {
33+
__call: (_self: any, message: string) => new Type(message),
34+
});
35+
}
36+
37+
export const Error: ErrorConstructor = initErrorClass(
38+
class implements Error {
39+
public name = "Error";
40+
public stack: string;
41+
42+
constructor(public message = "") {
43+
this.stack = getErrorStack((this.constructor as any).new);
44+
const metatable = getmetatable(this);
45+
if (!metatable.__errorToStringPatched) {
46+
metatable.__errorToStringPatched = true;
47+
metatable.__tostring = wrapErrorToString(metatable.__tostring);
48+
}
49+
}
50+
51+
public toString(): string {
52+
return this.message !== "" ? `${this.name}: ${this.message}` : this.name;
53+
}
54+
},
55+
"Error"
56+
);
57+
58+
function createErrorClass(name: string) {
59+
return initErrorClass(
60+
class extends Error {
61+
public name = name;
62+
},
63+
name
64+
);
65+
}
66+
67+
export const RangeError = createErrorClass("RangeError");
68+
export const ReferenceError = createErrorClass("ReferenceError");
69+
export const SyntaxError = createErrorClass("SyntaxError");
70+
export const TypeError = createErrorClass("TypeError");
71+
export const URIError = createErrorClass("URIError");

src/lualib/5.0/Generator.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { __TS__CountVarargs } from "./CountVarargs";
2+
import { GeneratorIterator } from "./GeneratorIterator";
3+
4+
function generatorIterator(this: GeneratorIterator) {
5+
return this;
6+
}
7+
8+
function generatorNext(this: GeneratorIterator, ...args: any[]) {
9+
const co = this.____coroutine;
10+
if (coroutine.status(co) === "dead") return { done: true };
11+
12+
const [status, value] = coroutine.resume(co, ...args);
13+
if (!status) throw value;
14+
15+
return { value, done: coroutine.status(co) === "dead" };
16+
}
17+
18+
export function __TS__Generator(this: void, fn: (this: void, ...args: any[]) => any) {
19+
return function (this: void, ...args: any[]): GeneratorIterator {
20+
const argsLength = __TS__CountVarargs(...args);
21+
return {
22+
// Using explicit this there, since we don't pass arguments after the first nil and context is likely to be nil
23+
____coroutine: coroutine.create(() => fn(...unpack(args, 1, argsLength))),
24+
[Symbol.iterator]: generatorIterator,
25+
next: generatorNext,
26+
};
27+
};
28+
}

src/lualib/5.0/Match.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/** @noSelfInFile */
2+
3+
export function __TS__Match(s: string, pattern: string, init?: number): LuaMultiReturn<string[]> {
4+
const [start, end, ...captures] = string.find(s, pattern, init);
5+
if (start === undefined || end === undefined) {
6+
return $multi();
7+
} else if (captures.length <= 0) {
8+
return $multi(s.slice(start - 1, end));
9+
} else {
10+
return $multi(...(captures as string[]));
11+
}
12+
}
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
const radixChars = "0123456789abcdefghijklmnopqrstuvwxyz";
22

33
function modf(this: void, x: number): LuaMultiReturn<[number, number]> {
4-
if (math.modf) {
5-
return math.modf(x);
6-
} else {
7-
const integral = x > 0 ? Math.floor(x) : Math.ceil(x);
8-
return $multi(integral, x - integral);
9-
}
4+
const integral = x > 0 ? Math.floor(x) : Math.ceil(x);
5+
return $multi(integral, x - integral);
106
}
117

128
// https://www.ecma-international.org/ecma-262/10.0/index.html#sec-number.prototype.tostring
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// TODO: In the future, change this to __TS__RegisterFileInfo and provide tstl interface to
2+
// get some metadata about transpilation.
3+
4+
import { __TS__Match } from "./Match";
5+
6+
interface SourceMap {
7+
[line: number]: number | { line: number; file: string };
8+
}
9+
10+
declare function __TS__originalTraceback(this: void, thread?: LuaThread, message?: string, level?: number);
11+
12+
export function __TS__SourceMapTraceBack(this: void, fileName: string, sourceMap: SourceMap): void {
13+
globalThis.__TS__sourcemap = globalThis.__TS__sourcemap || {};
14+
globalThis.__TS__sourcemap[fileName] = sourceMap;
15+
16+
if (globalThis.__TS__originalTraceback === undefined) {
17+
const originalTraceback = debug.traceback;
18+
globalThis.__TS__originalTraceback = originalTraceback;
19+
debug.traceback = ((thread, message, level) => {
20+
let trace: string;
21+
if (thread === undefined && message === undefined && level === undefined) {
22+
trace = originalTraceback();
23+
} else {
24+
trace = originalTraceback(`[Level ${level}] ${message}`);
25+
}
26+
27+
if (typeof trace !== "string") {
28+
return trace;
29+
}
30+
31+
const replacer = (file: string, srcFile: string, line: string) => {
32+
const fileSourceMap: SourceMap = globalThis.__TS__sourcemap[file];
33+
if (fileSourceMap && fileSourceMap[line]) {
34+
const data = fileSourceMap[line];
35+
if (typeof data === "number") {
36+
return `${srcFile}:${data}`;
37+
}
38+
39+
return `${data.file}:${data.line}`;
40+
}
41+
42+
return `${file}:${line}`;
43+
};
44+
45+
let [result] = string.gsub(trace, "(%S+)%.lua:(%d+)", (file, line) =>
46+
replacer(`${file}.lua`, `${file}.ts`, line)
47+
);
48+
49+
const stringReplacer = (file: string, line: string) => {
50+
const fileSourceMap: SourceMap = globalThis.__TS__sourcemap[file];
51+
if (fileSourceMap && fileSourceMap[line]) {
52+
const chunkName = __TS__Match(file, '%[string "([^"]+)"%]')[0];
53+
const [sourceName] = string.gsub(chunkName, ".lua$", ".ts");
54+
const data = fileSourceMap[line];
55+
if (typeof data === "number") {
56+
return `${sourceName}:${data}`;
57+
}
58+
59+
return `${data.file}:${data.line}`;
60+
}
61+
62+
return `${file}:${line}`;
63+
};
64+
[result] = string.gsub(result, '(%[string "[^"]+"%]):(%d+)', (file, line) => stringReplacer(file, line));
65+
66+
return result;
67+
}) as typeof debug.traceback;
68+
}
69+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { __TS__SparseArray } from "./SparseArray";
2+
3+
export function __TS__SparseArraySpread<T>(this: void, sparseArray: __TS__SparseArray<T>): LuaMultiReturn<T[]> {
4+
return unpack(sparseArray, 1, sparseArray.sparseLength);
5+
}

src/lualib/5.0/Unpack.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const __TS__Unpack = unpack;

src/lualib/Match.ts

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

0 commit comments

Comments
 (0)