Refactor, cleanup
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
import {
|
||||
type ILuaFunction,
|
||||
LuaBuiltinFunction,
|
||||
type LuaEnv,
|
||||
luaEquals,
|
||||
luaGet,
|
||||
LuaMultiRes,
|
||||
LuaRuntimeError,
|
||||
LuaTable,
|
||||
type LuaValue,
|
||||
} from "../runtime.ts";
|
||||
import { asyncQuickSort } from "../util.ts";
|
||||
|
||||
export const tableApi = new LuaTable({
|
||||
/**
|
||||
* Concatenates the elements of a table into a string, using a separator.
|
||||
* @param tbl - The table to concatenate.
|
||||
* @param sep - The separator to use between elements.
|
||||
* @param i - The start index.
|
||||
* @param j - The end index.
|
||||
* @returns The concatenated string.
|
||||
*/
|
||||
concat: new LuaBuiltinFunction(
|
||||
(_sf, tbl: LuaTable | any[], sep?: string, i?: number, j?: number) => {
|
||||
sep = sep ?? "";
|
||||
i = i ?? 1;
|
||||
j = j ?? tbl.length;
|
||||
if (Array.isArray(tbl)) {
|
||||
return tbl.slice(i - 1, j).join(sep);
|
||||
}
|
||||
const result = [];
|
||||
for (let k = i; k <= j; k++) {
|
||||
result.push(tbl.get(k));
|
||||
}
|
||||
return result.join(sep);
|
||||
},
|
||||
),
|
||||
/**
|
||||
* Inserts an element into a table at a specified position.
|
||||
* @param tbl - The table to insert the element into.
|
||||
* @param posOrValue - The position or value to insert.
|
||||
* @param value - The value to insert.
|
||||
*/
|
||||
insert: new LuaBuiltinFunction(
|
||||
(_sf, tbl: LuaTable | any[], posOrValue: number | any, value?: any) => {
|
||||
if (Array.isArray(tbl)) {
|
||||
if (value === undefined) {
|
||||
tbl.push(posOrValue);
|
||||
} else {
|
||||
tbl.splice(posOrValue - 1, 0, value);
|
||||
}
|
||||
} else if (tbl instanceof LuaTable) {
|
||||
if (value === undefined) {
|
||||
value = posOrValue;
|
||||
posOrValue = tbl.length + 1;
|
||||
}
|
||||
tbl.insert(value, posOrValue);
|
||||
}
|
||||
},
|
||||
),
|
||||
/**
|
||||
* Removes an element from a table at a specified position.
|
||||
* @param tbl - The table to remove the element from.
|
||||
* @param pos - The position of the element to remove.
|
||||
*/
|
||||
remove: new LuaBuiltinFunction((_sf, tbl: LuaTable | any[], pos?: number) => {
|
||||
pos = pos ?? tbl.length;
|
||||
if (Array.isArray(tbl)) {
|
||||
tbl.splice(pos - 1, 1);
|
||||
} else if (tbl instanceof LuaTable) {
|
||||
tbl.remove(pos);
|
||||
}
|
||||
}),
|
||||
/**
|
||||
* Sorts a table.
|
||||
* @param tbl - The table to sort.
|
||||
* @param comp - The comparison function.
|
||||
* @returns The sorted table.
|
||||
*/
|
||||
sort: new LuaBuiltinFunction(
|
||||
async (sf, tbl: LuaTable | any[], comp?: ILuaFunction) => {
|
||||
if (Array.isArray(tbl)) {
|
||||
tbl = await asyncQuickSort(tbl, async (a, b) => {
|
||||
if (comp) {
|
||||
return (await comp.call(sf, a, b)) ?? 0;
|
||||
} else {
|
||||
return a - b;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await tbl.sort(comp, sf);
|
||||
}
|
||||
return tbl;
|
||||
},
|
||||
),
|
||||
/**
|
||||
* Returns the keys of a table.
|
||||
* @param tbl - The table to get the keys from.
|
||||
* @returns The keys of the table.
|
||||
*/
|
||||
keys: new LuaBuiltinFunction((_sf, tbl: LuaTable | LuaEnv | any) => {
|
||||
if (tbl.keys) {
|
||||
return tbl.keys();
|
||||
} else {
|
||||
return Object.keys(tbl);
|
||||
}
|
||||
}),
|
||||
/**
|
||||
* Checks if a table (used as an array) contains a value.
|
||||
* @param tbl - The table to check.
|
||||
* @param value - The value to check for.
|
||||
* @returns True if the value is in the table, false otherwise.
|
||||
*/
|
||||
includes: new LuaBuiltinFunction(
|
||||
(sf, tbl: LuaTable | any[], value: LuaValue) => {
|
||||
if (!tbl) {
|
||||
return false;
|
||||
}
|
||||
if (tbl instanceof LuaTable) {
|
||||
// Iterate over the table
|
||||
for (const key of tbl.keys()) {
|
||||
if (luaEquals(tbl.get(key), value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (Array.isArray(tbl)) {
|
||||
return !!tbl.find((item) => luaEquals(item, value));
|
||||
} else {
|
||||
throw new LuaRuntimeError(
|
||||
`Cannot use includes on a non-table or non-array value`,
|
||||
sf,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
pack: new LuaBuiltinFunction((_sf, ...args: any[]) => {
|
||||
const tbl = new LuaTable();
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
tbl.set(i + 1, args[i]);
|
||||
}
|
||||
tbl.set("n", args.length);
|
||||
return tbl;
|
||||
}),
|
||||
unpack: new LuaBuiltinFunction(
|
||||
(_sf, tbl: LuaTable, i?: number, j?: number) => {
|
||||
i = i ?? 1;
|
||||
j = j ?? tbl.length;
|
||||
const result = [];
|
||||
for (let k = i; k <= j; k++) {
|
||||
result.push(tbl.get(k));
|
||||
}
|
||||
return new LuaMultiRes(result);
|
||||
},
|
||||
),
|
||||
|
||||
// Non-standard Lua functions
|
||||
/**
|
||||
* Finds an element in a table that matches a criteria function. Returns the first matching element.
|
||||
* @param tbl - The table to search.
|
||||
* @param criteriaFn - The criteria function.
|
||||
* @param fromIndex - The index to start searching from.
|
||||
* @returns Lua multi value of index, value, or nil if no element is found.
|
||||
*/
|
||||
find: new LuaBuiltinFunction(
|
||||
async (
|
||||
sf,
|
||||
tbl: LuaTable | any[],
|
||||
criteriaFn: ILuaFunction,
|
||||
fromIndex = 1,
|
||||
) => {
|
||||
const startIndex = fromIndex < 1 ? 1 : fromIndex;
|
||||
for (let i = startIndex; i <= tbl.length; i++) {
|
||||
const val = await luaGet(tbl, i, sf);
|
||||
if (await criteriaFn.call(sf, val)) {
|
||||
return new LuaMultiRes([i, val]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
});
|
||||
Reference in New Issue
Block a user