Skip to content

Commit fbb00d2

Browse files
PerryvwGlassBricks
andauthored
Lualib modules using a plugin to generate lualib (#1227)
* generate lualib with plugins * Copy over new lualib code * Lualib modules via plugin (#1224) * fix lualib-build * Finish lualib modules via plugin implementation * Include build-lualib.ts * Clean up lualib plugin with new plugin hooks * Fix mistake * Use plugin afterPrint results array to create bundle * Bundle lualib in correct order * Added tests for new plugin hooks * fix prettier * Remove lualibimport always option * updated snapshots * Remove obsolete error log * Use tstl CLI to build-lualib * Fix using tstl CLI to build lualib (#1233) Co-authored-by: Benjamin Ye <24237065+GlassBricks@users.noreply.github.com>
1 parent 3b41774 commit fbb00d2

File tree

135 files changed

+800
-406
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

135 files changed

+800
-406
lines changed

build-lualib.js

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

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@
1818
"dist/**/*.js",
1919
"dist/**/*.lua",
2020
"dist/**/*.ts",
21+
"dist/lualib/*.json",
2122
"language-extensions/**/*.ts"
2223
],
2324
"main": "dist/index.js",
2425
"types": "dist/index.d.ts",
2526
"scripts": {
2627
"build": "tsc && npm run build-lualib",
27-
"build-lualib": "node build-lualib.js",
28+
"build-lualib": "node dist/tstl.js -p src/lualib/tsconfig.json",
2829
"pretest": "npm run lint && npm run check:language-extensions && npm run build-lualib",
2930
"test": "jest",
3031
"lint": "npm run lint:eslint && npm run lint:prettier",

src/CompilerOptions.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export type CompilerOptions = OmitIndexSignature<ts.CompilerOptions> & {
4040

4141
export enum LuaLibImportKind {
4242
None = "none",
43-
Always = "always",
4443
Inline = "inline",
4544
Require = "require",
4645
}

src/LuaLib.ts

Lines changed: 76 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as path from "path";
22
import { EmitHost } from "./transpilation";
3+
import * as lua from "./LuaAST";
34

45
export enum LuaLibFeature {
56
ArrayConcat = "ArrayConcat",
@@ -99,81 +100,54 @@ export enum LuaLibFeature {
99100
Unpack = "Unpack",
100101
}
101102

102-
/* eslint-disable @typescript-eslint/naming-convention */
103-
const luaLibDependencies: Partial<Record<LuaLibFeature, LuaLibFeature[]>> = {
104-
ArrayConcat: [LuaLibFeature.ArrayIsArray],
105-
ArrayFlat: [LuaLibFeature.ArrayConcat, LuaLibFeature.ArrayIsArray],
106-
ArrayFlatMap: [LuaLibFeature.ArrayConcat, LuaLibFeature.ArrayIsArray],
107-
Await: [LuaLibFeature.InstanceOf, LuaLibFeature.New, LuaLibFeature.Promise],
108-
Decorate: [LuaLibFeature.ObjectGetOwnPropertyDescriptor, LuaLibFeature.SetDescriptor, LuaLibFeature.ObjectAssign],
109-
DelegatedYield: [LuaLibFeature.StringAccess],
110-
Delete: [LuaLibFeature.ObjectGetOwnPropertyDescriptors, LuaLibFeature.Error, LuaLibFeature.New],
111-
Error: [LuaLibFeature.Class, LuaLibFeature.ClassExtends, LuaLibFeature.New],
112-
FunctionBind: [LuaLibFeature.Unpack],
113-
Generator: [LuaLibFeature.Symbol],
114-
InstanceOf: [LuaLibFeature.Symbol],
115-
Iterator: [LuaLibFeature.Symbol],
116-
NumberToString: [LuaLibFeature.StringAccess],
117-
ObjectDefineProperty: [LuaLibFeature.CloneDescriptor, LuaLibFeature.SetDescriptor],
118-
ObjectFromEntries: [LuaLibFeature.Iterator, LuaLibFeature.Symbol],
119-
Promise: [
120-
LuaLibFeature.ArrayPush,
121-
LuaLibFeature.Class,
122-
LuaLibFeature.FunctionBind,
123-
LuaLibFeature.InstanceOf,
124-
LuaLibFeature.New,
125-
],
126-
PromiseAll: [LuaLibFeature.InstanceOf, LuaLibFeature.New, LuaLibFeature.Promise, LuaLibFeature.Iterator],
127-
PromiseAllSettled: [LuaLibFeature.InstanceOf, LuaLibFeature.New, LuaLibFeature.Promise, LuaLibFeature.Iterator],
128-
PromiseAny: [
129-
LuaLibFeature.ArrayPush,
130-
LuaLibFeature.InstanceOf,
131-
LuaLibFeature.New,
132-
LuaLibFeature.Promise,
133-
LuaLibFeature.Iterator,
134-
],
135-
PromiseRace: [
136-
LuaLibFeature.ArrayPush,
137-
LuaLibFeature.InstanceOf,
138-
LuaLibFeature.New,
139-
LuaLibFeature.Promise,
140-
LuaLibFeature.Iterator,
141-
],
142-
ParseFloat: [LuaLibFeature.StringAccess],
143-
ParseInt: [LuaLibFeature.StringSubstr, LuaLibFeature.StringSubstring],
144-
SetDescriptor: [LuaLibFeature.CloneDescriptor],
145-
Spread: [LuaLibFeature.Iterator, LuaLibFeature.StringAccess, LuaLibFeature.Unpack],
146-
StringSplit: [LuaLibFeature.StringSubstring, LuaLibFeature.StringAccess],
147-
SymbolRegistry: [LuaLibFeature.Symbol],
148-
149-
Map: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol, LuaLibFeature.Class],
150-
Set: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol, LuaLibFeature.Class],
151-
WeakMap: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol, LuaLibFeature.Class],
152-
WeakSet: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol, LuaLibFeature.Class],
153-
};
154-
/* eslint-enable @typescript-eslint/naming-convention */
155-
156-
export function loadLuaLibFeatures(features: Iterable<LuaLibFeature>, emitHost: EmitHost): string {
157-
let result = "";
103+
export interface LuaLibFeatureInfo {
104+
dependencies?: LuaLibFeature[];
105+
exports: string[];
106+
}
107+
export type LuaLibModulesInfo = Record<LuaLibFeature, LuaLibFeatureInfo>;
108+
109+
export const luaLibModulesInfoFileName = "lualib_module_info.json";
110+
let luaLibModulesInfo: LuaLibModulesInfo | undefined;
111+
export function getLuaLibModulesInfo(emitHost: EmitHost): LuaLibModulesInfo {
112+
if (luaLibModulesInfo === undefined) {
113+
const lualibPath = path.resolve(__dirname, `../dist/lualib/${luaLibModulesInfoFileName}`);
114+
const result = emitHost.readFile(lualibPath);
115+
if (result !== undefined) {
116+
luaLibModulesInfo = JSON.parse(result) as LuaLibModulesInfo;
117+
} else {
118+
throw new Error(`Could not load lualib dependencies from '${lualibPath}'`);
119+
}
120+
}
121+
return luaLibModulesInfo;
122+
}
158123

124+
export function readLuaLibFeature(feature: LuaLibFeature, emitHost: EmitHost): string {
125+
const featurePath = path.resolve(__dirname, `../dist/lualib/${feature}.lua`);
126+
const luaLibFeature = emitHost.readFile(featurePath);
127+
if (luaLibFeature === undefined) {
128+
throw new Error(`Could not load lualib feature from '${featurePath}'`);
129+
}
130+
return luaLibFeature;
131+
}
132+
133+
export function resolveRecursiveLualibFeatures(
134+
features: Iterable<LuaLibFeature>,
135+
emitHost: EmitHost,
136+
luaLibModulesInfo: LuaLibModulesInfo = getLuaLibModulesInfo(emitHost)
137+
): LuaLibFeature[] {
159138
const loadedFeatures = new Set<LuaLibFeature>();
139+
const result: LuaLibFeature[] = [];
160140

161141
function load(feature: LuaLibFeature): void {
162142
if (loadedFeatures.has(feature)) return;
163143
loadedFeatures.add(feature);
164144

165-
const dependencies = luaLibDependencies[feature];
145+
const dependencies = luaLibModulesInfo[feature]?.dependencies;
166146
if (dependencies) {
167147
dependencies.forEach(load);
168148
}
169149

170-
const featurePath = path.resolve(__dirname, `../dist/lualib/${feature}.lua`);
171-
const luaLibFeature = emitHost.readFile(featurePath);
172-
if (luaLibFeature !== undefined) {
173-
result += luaLibFeature + "\n";
174-
} else {
175-
throw new Error(`Could not load lualib feature from '${featurePath}'`);
176-
}
150+
result.push(feature);
177151
}
178152

179153
for (const feature of features) {
@@ -183,6 +157,44 @@ export function loadLuaLibFeatures(features: Iterable<LuaLibFeature>, emitHost:
183157
return result;
184158
}
185159

160+
export function loadInlineLualibFeatures(features: Iterable<LuaLibFeature>, emitHost: EmitHost): string {
161+
let result = "";
162+
163+
for (const feature of resolveRecursiveLualibFeatures(features, emitHost)) {
164+
const luaLibFeature = readLuaLibFeature(feature, emitHost);
165+
result += luaLibFeature + "\n";
166+
}
167+
168+
return result;
169+
}
170+
171+
export function loadImportedLualibFeatures(features: Iterable<LuaLibFeature>, emitHost: EmitHost): lua.Statement[] {
172+
const luaLibModuleInfo = getLuaLibModulesInfo(emitHost);
173+
174+
const imports = Array.from(features).flatMap(feature => luaLibModuleInfo[feature].exports);
175+
176+
const requireCall = lua.createCallExpression(lua.createIdentifier("require"), [
177+
lua.createStringLiteral("lualib_bundle"),
178+
]);
179+
if (imports.length === 0) {
180+
return [];
181+
}
182+
183+
const luaLibId = lua.createIdentifier("____lualib");
184+
const importStatement = lua.createVariableDeclarationStatement(luaLibId, requireCall);
185+
const statements: lua.Statement[] = [importStatement];
186+
// local <export> = ____luaLib.<export>
187+
for (const item of imports) {
188+
statements.push(
189+
lua.createVariableDeclarationStatement(
190+
lua.createIdentifier(item),
191+
lua.createTableIndexExpression(luaLibId, lua.createStringLiteral(item))
192+
)
193+
);
194+
}
195+
return statements;
196+
}
197+
186198
let luaLibBundleContent: string;
187199
export function getLuaLibBundle(emitHost: EmitHost): string {
188200
if (luaLibBundleContent === undefined) {

src/LuaPrinter.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import * as path from "path";
22
import { Mapping, SourceMapGenerator, SourceNode } from "source-map";
3-
import { getEmitPath } from ".";
43
import * as ts from "typescript";
54
import { CompilerOptions, isBundleEnabled, LuaLibImportKind } from "./CompilerOptions";
65
import * as lua from "./LuaAST";
7-
import { loadLuaLibFeatures, LuaLibFeature } from "./LuaLib";
6+
import { loadInlineLualibFeatures, LuaLibFeature, loadImportedLualibFeatures } from "./LuaLib";
87
import { isValidLuaIdentifier, shouldAllowUnicode } from "./transformation/utils/safe-names";
9-
import { EmitHost } from "./transpilation";
8+
import { EmitHost, getEmitPath } from "./transpilation";
109
import { intersperse, normalizeSlashes } from "./utils";
1110

1211
// https://www.lua.org/pil/2.4.html
@@ -233,18 +232,18 @@ export class LuaPrinter {
233232
if (!this.options.noHeader) {
234233
header += tstlHeader;
235234
}
235+
let statements = file.statements;
236236

237237
const luaLibImport = this.options.luaLibImport ?? LuaLibImportKind.Require;
238-
if (
239-
luaLibImport === LuaLibImportKind.Always ||
240-
(luaLibImport === LuaLibImportKind.Require && file.luaLibFeatures.size > 0)
241-
) {
242-
// Require lualib bundle
243-
header += 'require("lualib_bundle");\n';
238+
if (luaLibImport === LuaLibImportKind.Require && file.luaLibFeatures.size > 0) {
239+
// Import lualib features
240+
const importStatements = loadImportedLualibFeatures(file.luaLibFeatures, this.emitHost);
241+
242+
statements = importStatements.concat(statements);
244243
} else if (luaLibImport === LuaLibImportKind.Inline && file.luaLibFeatures.size > 0) {
245244
// Inline lualib features
246245
header += "-- Lua Library inline imports\n";
247-
header += loadLuaLibFeatures(file.luaLibFeatures, this.emitHost);
246+
header += loadInlineLualibFeatures(file.luaLibFeatures, this.emitHost);
248247
}
249248

250249
if (this.options.sourceMapTraceback && !isBundleEnabled(this.options)) {
@@ -253,7 +252,7 @@ export class LuaPrinter {
253252
header += `${LuaPrinter.sourceMapTracebackPlaceholder}\n`;
254253
}
255254

256-
return this.concatNodes(header, ...this.printStatementArray(file.statements));
255+
return this.concatNodes(header, ...this.printStatementArray(statements));
257256
}
258257

259258
protected pushIndent(): void {

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export { LuaLibFeature } from "./LuaLib";
88
export * from "./LuaPrinter";
99
export * from "./transformation/context";
1010
export * from "./transpilation";
11+
export { ProcessedFile } from "./transpilation/utils";

0 commit comments

Comments
 (0)