Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
893bfaa
feat: add flag for lua 5.0 target
YoRyan Apr 16, 2022
ceb7e96
feat(5.0): implement spread arguments
YoRyan Apr 16, 2022
4d17bb5
fix(5.0): in general, cases that apply to 5.1 should also apply to 5.0
YoRyan Apr 16, 2022
fdb322c
style: run prettier
YoRyan Apr 16, 2022
14f9421
test(5.0): share the expected results of the obvious cases with 5.1
YoRyan Apr 16, 2022
ff729e3
feat(5.0): work around the missing '#' and '%' operators
YoRyan Apr 17, 2022
635d271
fix: log the correct lua version for unsupported features
YoRyan Apr 20, 2022
2836859
style: condense spread table if branch
YoRyan Apr 20, 2022
fac16d2
test: add a special case for modulo for 5.0
YoRyan Apr 20, 2022
bb83e32
style: fix indentation for test function snippet
YoRyan Apr 20, 2022
927dba6
feat(5.0): implement spread element correctly
YoRyan Apr 24, 2022
64e5f6d
fix: report correct lua version in bitops diagnostic message
YoRyan Apr 24, 2022
a5f39f6
test: refactor spread tests to accomodate 5.0
YoRyan Apr 30, 2022
2399554
Revert "test: add a special case for modulo for 5.0"
YoRyan May 2, 2022
555e2f8
test: test basic numeric expressions against all versions
YoRyan May 2, 2022
afdc088
style: run prettier
YoRyan May 2, 2022
3a64a33
Merge branch 'TypeScriptToLua:master' into lua5.0
YoRyan May 5, 2022
85db0cb
refactor: use the convenience function to make an unpack call
YoRyan May 6, 2022
852febd
style(lualib): use @noselfinfile for the modulo polyfill
YoRyan May 7, 2022
3446474
Merge branch 'master' into lua5.0
YoRyan May 7, 2022
1f60fa3
fix: make bundling compatible with lua 5.0
YoRyan May 10, 2022
56727c9
fix(5.0): optimized single element array push for 5.0
YoRyan May 19, 2022
110e379
fix(5.0): fix constructor w/ instance fields for 5.0
YoRyan May 24, 2022
3f64c13
Merge branch 'master' into lua5.0
YoRyan Jul 23, 2022
bc89dce
fix(lualib): count varargs correctly with lua 5.0
YoRyan May 7, 2022
36324fb
fix(lualib): tracebacks don't support threads with lua 5.0
YoRyan May 7, 2022
18d3c7a
fix(lualib): work around missing math.modf() in lua 5.0
YoRyan May 7, 2022
f57f75b
fix(lualib): work around missing string.match() in lua 5.0
YoRyan May 8, 2022
3496d67
fix(lualib): detect lua 5.0 minor versions correctly
YoRyan May 8, 2022
fe45a47
refactor(lualib): lua 5.0 check can be a constant instead of a function
YoRyan May 8, 2022
937b776
Merge branch 'master' into lua5.0
YoRyan Aug 9, 2022
5eca07c
Merge branch 'lua5.0' into lua5.0-lualib
YoRyan Aug 9, 2022
da5fcb5
fix(5.0): get json test library to load
YoRyan Aug 16, 2022
b410d08
style: rename 5.0 json file
YoRyan Aug 17, 2022
2956058
style: use a better definition of infinity
YoRyan Aug 17, 2022
f0976df
feat(5.0): don't transform infinity to math.huge, which doesn't exist…
YoRyan Aug 17, 2022
36b93ae
Merge branch 'master' into lua5.0
YoRyan Aug 17, 2022
54f115c
Merge branch 'lua5.0-lualib' into lua5.0
YoRyan Aug 17, 2022
cc427a2
chore: bump lua-types version
YoRyan Aug 18, 2022
a1abb9e
feat: build another copy of lualib for 5.0
YoRyan Aug 18, 2022
41a219a
style: run prettier
YoRyan Aug 18, 2022
892b2cf
fix: small issues discovered in testing
YoRyan Aug 18, 2022
e187193
chore: bump lua-wasm-bindings version
YoRyan Aug 24, 2022
ccae8fd
fix(lualib): select() call was not using vararg optimization, breakin…
YoRyan Aug 25, 2022
8d9ce98
test: use inline lualib imports to get around problems with preloadin…
YoRyan Aug 25, 2022
d656050
test: remove old snapshots
YoRyan Aug 25, 2022
581fb52
fix: json files can't contain comments
YoRyan Aug 25, 2022
ab49bae
Revert "fix: json files can't contain comments"
YoRyan Aug 25, 2022
38b0288
test: exclude lualib-lua50 from coverage
YoRyan Aug 27, 2022
ced3532
style: move 5.0 tsconfig.json to existing lualib dir
YoRyan Aug 29, 2022
28cc8cd
style: refactor lualib resolution into common function
YoRyan Aug 29, 2022
d1bf66a
style: factor out table length transpilation into common function
YoRyan Aug 29, 2022
f2563cc
style: format 5.0 and non-5.0 require shims
YoRyan Aug 29, 2022
4ab5891
test: remove obsolete lua 5.0 arg test
YoRyan Aug 29, 2022
fdcea36
refactor(lualib): use builtins for the 5.0 branches instead of a vers…
YoRyan Aug 29, 2022
f390622
refactor(lualib): move 5.0-specific to its own directory
YoRyan Aug 30, 2022
c18a1fc
chore: add tsconfig to eslint
YoRyan Aug 30, 2022
e5e9723
refactor(lualib): reorganize dist/lualib directories to better suppor…
YoRyan Aug 30, 2022
e0d6206
fix(lualib): cache should account for multiple possible versions
YoRyan Aug 31, 2022
42f6de0
Revert "test: use inline lualib imports to get around problems with p…
YoRyan Aug 31, 2022
9b3a223
chore: adjust jest and npm configs for new lualib structure
YoRyan Aug 31, 2022
0953f26
refactor: cache lualib by file path so the universal target isn't cac…
YoRyan Aug 31, 2022
2dc07a8
chore: bump lua-types
YoRyan Sep 1, 2022
4715540
refactor: deduplicate require boilerplate
YoRyan Sep 1, 2022
3bc745c
refactor: simplify universal definition of TS_Match
YoRyan Sep 1, 2022
04b1a27
Merge branch 'master' into lua5.0
YoRyan Sep 2, 2022
236bd77
style: rename TS_Modulo -> TS_Modulo50
YoRyan Sep 2, 2022
9820e42
refactor(lualib): use unpack helper to avoid code duplication in Gene…
YoRyan Sep 2, 2022
5814859
refactor(lualib): eliminate duplication in SourceMapTraceBack.ts
YoRyan Sep 2, 2022
96c6f48
chore(lualib): fix comment in CountVarargs.ts
YoRyan Sep 2, 2022
cd9b219
refactor(lualib): eliminate duplication in Error.ts
YoRyan Sep 2, 2022
023b5e4
fix(lualib): modules info should be cached per-target
YoRyan Sep 2, 2022
9137683
refactor(lualib): eliminate duplication in NumbertToString.ts
YoRyan Sep 2, 2022
4713b69
refactor(lualib): modules info can also be cached by file path to avo…
YoRyan Sep 2, 2022
92a36a2
style: for locating lualib features, it makes more sense to default t…
YoRyan Sep 2, 2022
d7014a4
style: delete unnecessary noselfinfile
YoRyan Sep 2, 2022
7d90ef7
chore: add 5.0 target to tsconfig schema
YoRyan Sep 2, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
project: [
"test/tsconfig.json",
"src/lualib/tsconfig.json",
"src/lualib/tsconfig.lua50.json",
"benchmark/tsconfig.json",
"language-extensions/tsconfig.json",
],
Expand Down
52 changes: 36 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
"dist/**/*.js",
"dist/**/*.lua",
"dist/**/*.ts",
"dist/lualib/*.json",
"dist/lualib/**/*.json",
"language-extensions/**/*.ts"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc && npm run build-lualib",
"build-lualib": "node dist/tstl.js -p src/lualib/tsconfig.json",
"build-lualib": "node dist/tstl.js -p src/lualib/tsconfig.json && node dist/tstl.js -p src/lualib/tsconfig.lua50.json",
"pretest": "npm run lint && npm run check:language-extensions && npm run build-lualib",
"test": "jest",
"lint": "npm run lint:eslint && npm run lint:prettier",
Expand Down Expand Up @@ -65,8 +65,8 @@
"javascript-stringify": "^2.0.1",
"jest": "^28.1.3",
"jest-circus": "^29.0.1",
"lua-types": "^2.12.1",
"lua-wasm-bindings": "^0.2.2",
"lua-types": "^2.12.2",
"lua-wasm-bindings": "^0.3.1",
"prettier": "^2.3.2",
"ts-jest": "^28.0.8",
"ts-node": "^10.9.1",
Expand Down
1 change: 1 addition & 0 deletions src/CompilerOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export enum LuaLibImportKind {

export enum LuaTarget {
Universal = "universal",
Lua50 = "5.0",
Lua51 = "5.1",
Lua52 = "5.2",
Lua53 = "5.3",
Expand Down
16 changes: 15 additions & 1 deletion src/LuaAST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export enum SyntaxKind {
NumericLiteral,
NilKeyword,
DotsKeyword,
ArgKeyword,
TrueKeyword,
FalseKeyword,
FunctionExpression,
Expand Down Expand Up @@ -544,6 +545,18 @@ export function createDotsLiteral(tsOriginal?: ts.Node): DotsLiteral {
return createNode(SyntaxKind.DotsKeyword, tsOriginal) as DotsLiteral;
}

export interface ArgLiteral extends Expression {
kind: SyntaxKind.ArgKeyword;
}

export function isArgLiteral(node: Node): node is ArgLiteral {
return node.kind === SyntaxKind.ArgKeyword;
}

export function createArgLiteral(tsOriginal?: ts.Node): ArgLiteral {
return createNode(SyntaxKind.ArgKeyword, tsOriginal) as ArgLiteral;
}

// StringLiteral / NumberLiteral
// TODO TS uses the export interface "LiteralLikeNode" with a "text: string" member
// but since we don't parse from text I think we can simplify by just having a value member
Expand Down Expand Up @@ -581,10 +594,11 @@ export function createStringLiteral(value: string, tsOriginal?: ts.Node): String

export function isLiteral(
node: Node
): node is NilLiteral | DotsLiteral | BooleanLiteral | NumericLiteral | StringLiteral {
): node is NilLiteral | DotsLiteral | ArgLiteral | BooleanLiteral | NumericLiteral | StringLiteral {
return (
isNilLiteral(node) ||
isDotsLiteral(node) ||
isArgLiteral(node) ||
isBooleanLiteral(node) ||
isNumericLiteral(node) ||
isStringLiteral(node)
Expand Down
59 changes: 39 additions & 20 deletions src/LuaLib.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as path from "path";
import { EmitHost } from "./transpilation";
import * as lua from "./LuaAST";
import { LuaTarget } from "./CompilerOptions";

export enum LuaLibFeature {
ArrayConcat = "ArrayConcat",
Expand Down Expand Up @@ -34,6 +35,7 @@ export enum LuaLibFeature {
Class = "Class",
ClassExtends = "ClassExtends",
CloneDescriptor = "CloneDescriptor",
CountVarargs = "CountVarargs",
Decorate = "Decorate",
DecorateParam = "DecorateParam",
Delete = "Delete",
Expand All @@ -46,8 +48,11 @@ export enum LuaLibFeature {
Iterator = "Iterator",
LuaIteratorSpread = "LuaIteratorSpread",
Map = "Map",
Match = "Match",
MathAtan2 = "MathAtan2",
MathModf = "MathModf",
MathSign = "MathSign",
Modulo50 = "Modulo50",
New = "New",
Number = "Number",
NumberIsFinite = "NumberIsFinite",
Expand Down Expand Up @@ -107,23 +112,28 @@ export interface LuaLibFeatureInfo {
}
export type LuaLibModulesInfo = Record<LuaLibFeature, LuaLibFeatureInfo>;

export function resolveLuaLibDir(luaTarget: LuaTarget) {
const luaLibDir = luaTarget === LuaTarget.Lua50 ? "5.0" : "universal";
return path.resolve(__dirname, path.join("..", "dist", "lualib", luaLibDir));
}

export const luaLibModulesInfoFileName = "lualib_module_info.json";
let luaLibModulesInfo: LuaLibModulesInfo | undefined;
export function getLuaLibModulesInfo(emitHost: EmitHost): LuaLibModulesInfo {
if (luaLibModulesInfo === undefined) {
const lualibPath = path.resolve(__dirname, `../dist/lualib/${luaLibModulesInfoFileName}`);
const luaLibModulesInfo = new Map<string, LuaLibModulesInfo>();
export function getLuaLibModulesInfo(luaTarget: LuaTarget, emitHost: EmitHost): LuaLibModulesInfo {
const lualibPath = path.join(resolveLuaLibDir(luaTarget), luaLibModulesInfoFileName);
if (!luaLibModulesInfo.has(lualibPath)) {
const result = emitHost.readFile(lualibPath);
if (result !== undefined) {
luaLibModulesInfo = JSON.parse(result) as LuaLibModulesInfo;
luaLibModulesInfo.set(lualibPath, JSON.parse(result) as LuaLibModulesInfo);
} else {
throw new Error(`Could not load lualib dependencies from '${lualibPath}'`);
}
}
return luaLibModulesInfo;
return luaLibModulesInfo.get(lualibPath) as LuaLibModulesInfo;
}

export function readLuaLibFeature(feature: LuaLibFeature, emitHost: EmitHost): string {
const featurePath = path.resolve(__dirname, `../dist/lualib/${feature}.lua`);
export function readLuaLibFeature(feature: LuaLibFeature, luaTarget: LuaTarget, emitHost: EmitHost): string {
const featurePath = path.join(resolveLuaLibDir(luaTarget), `${feature}.lua`);
const luaLibFeature = emitHost.readFile(featurePath);
if (luaLibFeature === undefined) {
throw new Error(`Could not load lualib feature from '${featurePath}'`);
Expand All @@ -133,8 +143,9 @@ export function readLuaLibFeature(feature: LuaLibFeature, emitHost: EmitHost): s

export function resolveRecursiveLualibFeatures(
features: Iterable<LuaLibFeature>,
luaTarget: LuaTarget,
emitHost: EmitHost,
luaLibModulesInfo: LuaLibModulesInfo = getLuaLibModulesInfo(emitHost)
luaLibModulesInfo: LuaLibModulesInfo = getLuaLibModulesInfo(luaTarget, emitHost)
): LuaLibFeature[] {
const loadedFeatures = new Set<LuaLibFeature>();
const result: LuaLibFeature[] = [];
Expand All @@ -158,19 +169,27 @@ export function resolveRecursiveLualibFeatures(
return result;
}

export function loadInlineLualibFeatures(features: Iterable<LuaLibFeature>, emitHost: EmitHost): string {
export function loadInlineLualibFeatures(
features: Iterable<LuaLibFeature>,
luaTarget: LuaTarget,
emitHost: EmitHost
): string {
let result = "";

for (const feature of resolveRecursiveLualibFeatures(features, emitHost)) {
const luaLibFeature = readLuaLibFeature(feature, emitHost);
for (const feature of resolveRecursiveLualibFeatures(features, luaTarget, emitHost)) {
const luaLibFeature = readLuaLibFeature(feature, luaTarget, emitHost);
result += luaLibFeature + "\n";
}

return result;
}

export function loadImportedLualibFeatures(features: Iterable<LuaLibFeature>, emitHost: EmitHost): lua.Statement[] {
const luaLibModuleInfo = getLuaLibModulesInfo(emitHost);
export function loadImportedLualibFeatures(
features: Iterable<LuaLibFeature>,
luaTarget: LuaTarget,
emitHost: EmitHost
): lua.Statement[] {
const luaLibModuleInfo = getLuaLibModulesInfo(luaTarget, emitHost);

const imports = Array.from(features).flatMap(feature => luaLibModuleInfo[feature].exports);

Expand All @@ -196,17 +215,17 @@ export function loadImportedLualibFeatures(features: Iterable<LuaLibFeature>, em
return statements;
}

let luaLibBundleContent: string;
export function getLuaLibBundle(emitHost: EmitHost): string {
if (luaLibBundleContent === undefined) {
const lualibPath = path.resolve(__dirname, "../dist/lualib/lualib_bundle.lua");
const luaLibBundleContent = new Map<string, string>();
export function getLuaLibBundle(luaTarget: LuaTarget, emitHost: EmitHost): string {
const lualibPath = path.join(resolveLuaLibDir(luaTarget), "lualib_bundle.lua");
if (!luaLibBundleContent.has(lualibPath)) {
const result = emitHost.readFile(lualibPath);
if (result !== undefined) {
luaLibBundleContent = result;
luaLibBundleContent.set(lualibPath, result);
} else {
throw new Error(`Could not load lualib bundle from '${lualibPath}'`);
}
}

return luaLibBundleContent;
return luaLibBundleContent.get(lualibPath) as string;
}
15 changes: 12 additions & 3 deletions src/LuaPrinter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as path from "path";
import { Mapping, SourceMapGenerator, SourceNode } from "source-map";
import * as ts from "typescript";
import { CompilerOptions, isBundleEnabled, LuaLibImportKind } from "./CompilerOptions";
import { CompilerOptions, isBundleEnabled, LuaLibImportKind, LuaTarget } from "./CompilerOptions";
import * as lua from "./LuaAST";
import { loadInlineLualibFeatures, LuaLibFeature, loadImportedLualibFeatures } from "./LuaLib";
import { isValidLuaIdentifier, shouldAllowUnicode } from "./transformation/utils/safe-names";
Expand Down Expand Up @@ -233,14 +233,17 @@ export class LuaPrinter {
sourceChunks.push(tstlHeader);
}

const luaTarget = this.options.luaTarget ?? LuaTarget.Universal;
const luaLibImport = this.options.luaLibImport ?? LuaLibImportKind.Require;
if (luaLibImport === LuaLibImportKind.Require && file.luaLibFeatures.size > 0) {
// Import lualib features
sourceChunks = this.printStatementArray(loadImportedLualibFeatures(file.luaLibFeatures, this.emitHost));
sourceChunks = this.printStatementArray(
loadImportedLualibFeatures(file.luaLibFeatures, luaTarget, this.emitHost)
);
} else if (luaLibImport === LuaLibImportKind.Inline && file.luaLibFeatures.size > 0) {
// Inline lualib features
sourceChunks.push("-- Lua Library inline imports\n");
sourceChunks.push(loadInlineLualibFeatures(file.luaLibFeatures, this.emitHost));
sourceChunks.push(loadInlineLualibFeatures(file.luaLibFeatures, luaTarget, this.emitHost));
sourceChunks.push("-- End of Lua Library inline imports\n");
}

Expand Down Expand Up @@ -583,6 +586,8 @@ export class LuaPrinter {
return this.printNilLiteral(expression as lua.NilLiteral);
case lua.SyntaxKind.DotsKeyword:
return this.printDotsLiteral(expression as lua.DotsLiteral);
case lua.SyntaxKind.ArgKeyword:
return this.printArgLiteral(expression as lua.ArgLiteral);
case lua.SyntaxKind.TrueKeyword:
case lua.SyntaxKind.FalseKeyword:
return this.printBooleanLiteral(expression as lua.BooleanLiteral);
Expand Down Expand Up @@ -625,6 +630,10 @@ export class LuaPrinter {
return this.createSourceNode(expression, "...");
}

public printArgLiteral(expression: lua.ArgLiteral): SourceNode {
return this.createSourceNode(expression, "arg");
}

public printBooleanLiteral(expression: lua.BooleanLiteral): SourceNode {
return this.createSourceNode(expression, expression.kind === lua.SyntaxKind.TrueKeyword ? "true" : "false");
}
Expand Down
13 changes: 12 additions & 1 deletion src/lualib-build/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,23 @@ class LuaLibPlugin implements tstl.Plugin {
emitBOM
);

// Flatten the output folder structure; we do not want to keep the target-specific directories
for (const file of result) {
let outPath = file.fileName;
while (outPath.includes("lualib") && path.basename(path.dirname(outPath)) !== "lualib") {
const upOne = path.join(path.dirname(outPath), "..", path.basename(outPath));
outPath = path.normalize(upOne);
}
file.fileName = outPath;
}

// Create map of result files keyed by their 'lualib name'
const exportedLualibFeatures = new Map(result.map(f => [path.basename(f.fileName).split(".")[0], f.code]));

// Figure out the order required in the bundle by recursively resolving all dependency features
const allFeatures = Object.values(LuaLibFeature) as LuaLibFeature[];
const orderedFeatures = resolveRecursiveLualibFeatures(allFeatures, emitHost, luaLibModuleInfo);
const luaTarget = options.luaTarget ?? tstl.LuaTarget.Universal;
const orderedFeatures = resolveRecursiveLualibFeatures(allFeatures, luaTarget, emitHost, luaLibModuleInfo);

// Concatenate lualib files into bundle with exports table and add lualib_bundle.lua to results
let lualibBundle = orderedFeatures.map(f => exportedLualibFeatures.get(LuaLibFeature[f])).join("\n");
Expand Down
7 changes: 7 additions & 0 deletions src/lualib/5.0/CountVarargs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @noSelfInFile */

export function __TS__CountVarargs<T>(...args: T[]): number {
// select() is not available in Lua 5.0. In this version, the arg table
// includes trailing nils.
return args.length;
}
Loading