Lua: table.select API

This commit is contained in:
Zef Hemel
2026-01-27 09:00:37 +01:00
parent fe800417bc
commit 2e469ba3ea
3 changed files with 99 additions and 24 deletions
+31 -1
View File
@@ -11,7 +11,7 @@ import {
type LuaValue,
luaValueToJS,
} from "../runtime.ts";
import { asyncQuickSort } from "../util.ts";
import { asyncQuickSort, evalPromiseValues } from "../util.ts";
export const tableApi = new LuaTable({
/**
@@ -99,6 +99,7 @@ export const tableApi = new LuaTable({
),
/**
* Returns the keys of a table.
* Note: Space Lua specific
* @param tbl - The table to get the keys from.
* @returns The keys of the table.
*/
@@ -111,6 +112,7 @@ export const tableApi = new LuaTable({
}),
/**
* Checks if a table (used as an array) contains a value.
* Note: Space Lua specific
* @param tbl - The table to check.
* @param value - The value to check for.
* @returns True if the value is in the table, false otherwise.
@@ -138,6 +140,34 @@ export const tableApi = new LuaTable({
}
},
),
/**
* Returns a new table from an old one, only with selected keys
* @param tbl a Lua table or JS object
* @param keys a list of keys to select from the table, if keys[0] is a table or array, assumed to contain the keys to select
* @returns a new table with only the selected keys
*/
select: new LuaBuiltinFunction(
(sf, tbl: LuaTable | Record<string, any>, ...keys: LuaValue[]) => {
// Normalize arguments
if (Array.isArray(keys[0])) {
// First argument is key array, let's unpack
keys = keys[0];
} else if (keys[0] instanceof LuaTable) {
keys = keys[0].toJSArray();
}
const resultTable = new LuaTable();
const setPromises: (void | Promise<void>)[] = [];
for (const key of keys) {
setPromises.push(resultTable.set(key, luaGet(tbl, key, null, sf)));
}
const promised = evalPromiseValues(setPromises);
if (promised instanceof Promise) {
return promised.then(() => resultTable);
} else {
return resultTable;
}
},
),
pack: new LuaBuiltinFunction((_sf, ...args: any[]) => {
const tbl = new LuaTable();
for (let i = 0; i < args.length; i++) {
+37 -2
View File
@@ -1,9 +1,37 @@
function deepCompare(t1, t2)
if t1 == t2 then return true end
-- If they are the same object, return true
if type(t1) ~= "table" or type(t2) ~= "table" then return false end
-- If not both tables, return false
-- Check if both tables have the same number of keys
local t1_keys = 0
local t2_keys = 0
for k in pairs(t1) do
t1_keys = t1_keys + 1
end
for k in pairs(t2) do
t2_keys = t2_keys + 1
end
if t1_keys ~= t2_keys then return false end
-- Recursively compare each key-value pair
for k, v in pairs(t1) do
if not deepCompare(v, t2[k]) then
return false
end
end
return true
end
local function assertEqual(a, b)
if a ~= b then
error("Assertion failed: " .. a .. " is not equal to " .. b)
if not deepCompare(a, b) then
error("Assertion failed: " .. tostring(a) .. " is not equal to " .. tostring(b))
end
end
-- Basic table operations
local t = { 1, 2, 3 }
table.insert(t, 4)
@@ -155,3 +183,10 @@ local idx, two = table.find(t, function(v) return v == 2 end)
assertEqual(idx, 3)
assertEqual(two, 2)
assertEqual(table.find(t, function(v) return v == 4 end), nil)
-- Test table.select
local tbl = {name = "Pete", age = 100, parents = {"John", "Jane"}}
assertEqual(table.select(tbl, "name"), {name = "Pete"})
assertEqual(table.select(tbl, {"name"}), {name = "Pete"})
assertEqual(table.select(tbl, "name", "age"), { name = "Pete", age = 100})
assertEqual(table.select(tbl, "name", "age", "non-existing"), { name = "Pete", age = 100})