Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 4 additions & 6 deletions build_lualib.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as fs from "fs";
import * as glob from "glob";
import {compile} from "./src/Compiler";
import {LuaLib as luaLib, LuaLibFeature} from "./src/LuaLib";

const bundlePath = "./dist/lualib/lualib_bundle.lua";

Expand All @@ -15,14 +16,11 @@ compile([
"--rootDir",
"./src/lualib",
...glob.sync("./src/lualib/*.ts"),
]);
]);

if (fs.existsSync(bundlePath)) {
fs.unlinkSync(bundlePath);
fs.unlinkSync(bundlePath);
}

let bundle = "";

glob.sync("./dist/lualib/*.lua").forEach(fileName => bundle += fs.readFileSync(fileName));

const bundle = luaLib.loadFeatures(Object.keys(LuaLibFeature).map(lib => LuaLibFeature[lib]));
fs.writeFileSync(bundlePath, bundle);
2 changes: 2 additions & 0 deletions src/Decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class Decorator {
case "phantom": return DecoratorKind.Phantom;
case "tuplereturn": return DecoratorKind.TupleReturn;
case "noclassor": return DecoratorKind.NoClassOr;
case "luaiterator": return DecoratorKind.LuaIterator;
}

return undefined;
Expand All @@ -37,4 +38,5 @@ export enum DecoratorKind {
Phantom = "Phantom",
TupleReturn = "TupleReturn",
NoClassOr = "NoClassOr",
LuaIterator = "LuaIterator",
}
7 changes: 7 additions & 0 deletions src/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,11 @@ export class TSTLErrors {
node);
}
}

public static UnsupportedNonDestructuringLuaIterator = (node: ts.Node) => {
return new TranspileError("Unsupported use of lua iterator with TupleReturn decorator in for...of statement. "
+ "You must use a destructuring statement to catch results from a lua iterator with "
+ "the TupleReturn decorator.",
node);
}
}
60 changes: 60 additions & 0 deletions src/LuaLib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as fs from "fs";
import * as path from "path";

export enum LuaLibFeature {
ArrayConcat = "ArrayConcat",
ArrayEvery = "ArrayEvery",
ArrayFilter = "ArrayFilter",
ArrayForEach = "ArrayForEach",
ArrayIndexOf = "ArrayIndexOf",
ArrayMap = "ArrayMap",
ArrayPush = "ArrayPush",
ArrayReverse = "ArrayReverse",
ArrayShift = "ArrayShift",
ArrayUnshift = "ArrayUnshift",
ArraySort = "ArraySort",
ArraySlice = "ArraySlice",
ArraySome = "ArraySome",
ArraySplice = "ArraySplice",
FunctionApply = "FunctionApply",
FunctionBind = "FunctionBind",
FunctionCall = "FunctionCall",
InstanceOf = "InstanceOf",
Iterator = "Iterator",
Map = "Map",
Set = "Set",
StringReplace = "StringReplace",
StringSplit = "StringSplit",
Symbol = "Symbol",
Ternary = "Ternary",
}

const luaLibDependencies: { [lib in LuaLibFeature]?: LuaLibFeature[] } = {
Iterator: [LuaLibFeature.Symbol],
Map: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol],
Set: [LuaLibFeature.InstanceOf, LuaLibFeature.Iterator, LuaLibFeature.Symbol],
};

export class LuaLib {
public static loadFeatures(features: Iterable<LuaLibFeature>): string {
let result = "";

const loadedFeatures = new Set<LuaLibFeature>();

function load(feature: LuaLibFeature): void {
if (!loadedFeatures.has(feature)) {
loadedFeatures.add(feature);
if (luaLibDependencies[feature]) {
luaLibDependencies[feature].forEach(load);
}
const featureFile = path.resolve(__dirname, `../dist/lualib/${feature}.lua`);
result += fs.readFileSync(featureFile).toString() + "\n";
}
}

for (const feature of features) {
load(feature);
}
return result;
}
}
14 changes: 13 additions & 1 deletion src/TSHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,16 @@ export class TSHelper {
return this.forTypeOrAnySupertype(type, checker, t => this.isExplicitArrayType(t, checker));
}

public static isLuaIteratorCall(node: ts.Node, checker: ts.TypeChecker): boolean {
if (ts.isCallExpression(node) && node.parent && ts.isForOfStatement(node.parent)) {
const type = checker.getTypeAtLocation(node.expression);
return this.getCustomDecorators(type, checker)
.has(DecoratorKind.LuaIterator);
} else {
return false;
}
}

public static isTupleReturnCall(node: ts.Node, checker: ts.TypeChecker): boolean {
if (ts.isCallExpression(node)) {
const type = checker.getTypeAtLocation(node.expression);
Expand All @@ -157,7 +167,9 @@ export class TSHelper {
checker.getTypeAtLocation(declaration),
checker
);
return decorators.has(DecoratorKind.TupleReturn);
return decorators.has(DecoratorKind.TupleReturn)
// Lua iterators are not 'true' tupleReturn functions as they actually return a function
&& !decorators.has(DecoratorKind.LuaIterator);
} else {
return false;
}
Expand Down
Loading