diff --git a/common/space_lua/language_core_test.lua b/common/space_lua/language_core_test.lua index f6a77ca2..b2a1e859 100644 --- a/common/space_lua/language_core_test.lua +++ b/common/space_lua/language_core_test.lua @@ -65,7 +65,7 @@ assert(a == 1 and b == 2) assert(addAll(1, 2, 3) == 6) -- Test multiple return values in expressions assertEqual(addAll(multi_return()), 3) -assertEqual(#{multi_return()}, 2) +assertEqual(#{ multi_return() }, 2) local a, b, c = 0, multi_return() assert(a == 0 and b == 1 and c == 2) @@ -393,6 +393,11 @@ local function collect_range(from, to, step) return values end +local tblNew = { 1, 2, 3 } +table.insert(tblNew, 4) +assertEqual(#tblNew, 4) +assertEqual(tblNew[4], 4) + local values1 = collect_range(1, 5, 2) assert(#values1 == 3, "Range with step 2 should return 3 values") assert(values1[1] == 1 and values1[2] == 3 and values1[3] == 5, "Range values with step 2 should be correct") diff --git a/common/space_lua/stdlib/table.ts b/common/space_lua/stdlib/table.ts index 2576eeba..f9668a75 100644 --- a/common/space_lua/stdlib/table.ts +++ b/common/space_lua/stdlib/table.ts @@ -8,6 +8,7 @@ import { LuaTable, type LuaValue, } from "$common/space_lua/runtime.ts"; +import { asyncQuickSort } from "$common/space_lua/util.ts"; export const tableApi = new LuaTable({ /** @@ -20,12 +21,12 @@ export const tableApi = new LuaTable({ */ concat: new LuaBuiltinFunction( (_sf, tbl: LuaTable | any[], sep?: string, i?: number, j?: number) => { - if (Array.isArray(tbl)) { - return tbl.join(sep); - } 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)); @@ -40,15 +41,19 @@ export const tableApi = new LuaTable({ * @param value - The value to insert. */ insert: new LuaBuiltinFunction( - (_sf, tbl: LuaTable, posOrValue: number | any, value?: any) => { - if (value === undefined) { - let pos = 1; - while (tbl.get(pos) !== null) { - pos++; + (_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); } - tbl.set(pos, posOrValue); - } else { - tbl.insert(posOrValue, value); + } else if (tbl instanceof LuaTable) { + if (value === undefined) { + value = posOrValue; + posOrValue = tbl.length + 1; + } + tbl.insert(value, posOrValue); } }, ), @@ -57,9 +62,13 @@ export const tableApi = new LuaTable({ * @param tbl - The table to remove the element from. * @param pos - The position of the element to remove. */ - remove: new LuaBuiltinFunction((_sf, tbl: LuaTable, pos?: number) => { + remove: new LuaBuiltinFunction((_sf, tbl: LuaTable | any[], pos?: number) => { pos = pos ?? tbl.length; - tbl.remove(pos); + if (Array.isArray(tbl)) { + tbl.splice(pos - 1, 1); + } else if (tbl instanceof LuaTable) { + tbl.remove(pos); + } }), /** * Sorts a table. @@ -67,16 +76,33 @@ export const tableApi = new LuaTable({ * @param comp - The comparison function. * @returns The sorted table. */ - sort: new LuaBuiltinFunction((sf, tbl: LuaTable, comp?: ILuaFunction) => { - return tbl.sort(comp, sf); - }), + 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) => { - return tbl.keys(); + 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. diff --git a/common/space_lua/stdlib/table_test.lua b/common/space_lua/stdlib/table_test.lua index 35f6536f..8d73f10a 100644 --- a/common/space_lua/stdlib/table_test.lua +++ b/common/space_lua/stdlib/table_test.lua @@ -9,10 +9,25 @@ local t = { 1, 2, 3 } table.insert(t, 4) assertEqual(t[4], 4) table.remove(t, 1) -assertEqual(t[1], 2) -table.insert(t, 1, 1) -assertEqual(t[1], 1) +table.remove(t) +assertEqual(t[2], 3) +assertEqual(#t, 2) + +t = js.tojs({ 1, 2, 3 }) +table.insert(t, 4) +assertEqual(t[4], 4) +table.remove(t, 1) +table.remove(t) +assertEqual(t[2], 3) +assertEqual(#t, 2) + + +-- Test concat assertEqual(table.concat({ "Hello", "world" }, " "), "Hello world") +assertEqual(table.concat({ "Hello", "world", "three" }, " ", 2, 3), "world three") + +-- Test with JavaScript array +assertEqual(table.concat(js.tojs({ "Hello", "world", "three" }), " ", 2, 3), "world three") -- Table sorting local t = { 3, 1, 2 } @@ -37,6 +52,21 @@ end) assertEqual(data[1].name, "Jane") assertEqual(data[2].name, "John") +-- Now the same with js.tojs +local data = js.tojs { 1, 3, 2 } +table.sort(data) +assertEqual(data[1], 1) +assertEqual(data[2], 2) +assertEqual(data[3], 3) + +local data = js.tojs { { name = "John", age = 30 }, { name = "Jane", age = 25 } } +table.sort(data, function(a, b) + return a.age < b.age +end) +assertEqual(data[1].name, "Jane") +assertEqual(data[2].name, "John") + + -- ipairs tests local p = ipairs({ 3, 2, 1 }) local idx, value = p() @@ -102,12 +132,12 @@ local success, error = pcall(function() table.includes("not a table", 1) end) assert(not success) -assert(string.find(error, "Cannot use includes")) +assert(string.find(error, "Cannot use includes")) -- Test pack and unpack local t = { 1, 2, 3 } local packed = table.pack(table.unpack(t)) assertEqual(packed[1], 1) assertEqual(packed[2], 2) -assertEqual(packed[3], 3) -assertEqual(packed.n, 3) \ No newline at end of file +assertEqual(packed[3], 3) +assertEqual(packed.n, 3)