From a609108aa764aa5ac9102fd3d5bba89a191113d6 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 27 May 2026 11:18:17 +0200 Subject: [PATCH 1/5] fix deprecations for zig 0.17 array multiplication is removed in 0.17 `@splat(0)` pattern works in both 0.16 and 0.17 --- src/lib.zig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib.zig b/src/lib.zig index cf8eee9..5e7dfe1 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -205,7 +205,7 @@ pub const DebugInfo51 = struct { L: bool = false, fn toString(options: Options) [10:0]u8 { - var str = [_:0]u8{0} ** 10; + var str: [10:0]u8 = @splat(0); var index: u8 = 0; inline for (std.meta.fields(Options)) |field| { @@ -257,7 +257,7 @@ const DebugInfo52 = struct { L: bool = false, fn toString(options: Options) [10:0]u8 { - var str = [_:0]u8{0} ** 10; + var str: [10:0]u8 = @splat(0); var index: u8 = 0; inline for (std.meta.fields(Options)) |field| { @@ -314,7 +314,7 @@ const DebugInfo54 = struct { L: bool = false, fn toString(options: Options) [10:0]u8 { - var str = [_:0]u8{0} ** 10; + var str: [10:0]u8 = @splat(0); var index: u8 = 0; inline for (std.meta.fields(Options)) |field| { @@ -371,7 +371,7 @@ const DebugInfo55 = struct { L: bool = false, fn toString(options: Options) [10:0]u8 { - var str = [_:0]u8{0} ** 10; + var str: [10:0]u8 = @splat(0); var index: u8 = 0; inline for (std.meta.fields(Options)) |field| { @@ -413,7 +413,7 @@ pub const DebugInfoLuau = struct { L: bool = false, fn toString(options: Options) [10:0]u8 { - var str = [_:0]u8{0} ** 10; + var str: [10:0]u8 = @splat(0); var index: u8 = 0; inline for (std.meta.fields(Options)) |field| { @@ -5451,7 +5451,7 @@ pub fn wrap(comptime function: anytype) TypeOfWrap(function) { const lua: *Lua = @ptrCast(state.?); if (str) |s| { const buf = s[0..len]; - return @call(.always_inline, function, .{lua, buf}); + return @call(.always_inline, function, .{ lua, buf }); } return -1; } From 1dcb9f2b7b466a1609cc11e746c2efc4f17685da Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Sat, 30 May 2026 17:16:27 -0600 Subject: [PATCH 2/5] Fix opening bitlib and vector docs There was an additional pop() on the bitlib open that was causing issues when enabling apicheck in luajit. This is only needed in Lua 5.2 Also fixed bad logic on openVector. Closes #212 --- src/lib.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.zig b/src/lib.zig index 5e7dfe1..887743e 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -4496,7 +4496,8 @@ pub const Lua = opaque { .luajit => lua.requireF(c.LUA_BITLIBNAME, c.luaopen_bit, true), else => @compileError(@src().fn_name ++ " is only available in Lua 5.2 and LuaJIT."), } - lua.pop(1); + // For some reason Lua 5.2 leaves a value on the stack. + if (lang == .lua52) lua.pop(1); } pub const openBit = openBit32; @@ -4508,9 +4509,8 @@ pub const Lua = opaque { /// * Pushes to Stack: `0` /// * Lua Runtime Errors: `any` pub fn openVector(lua: *Lua) void { - if (lang == .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); lua.requireF(c.LUA_VECLIBNAME, c.luaopen_vector, true); - if (lang == .lua52 or lang == .lua53 or lang == .lua54 or lang == .lua55) lua.pop(1); } /// Returns if given typeinfo is a string type From d59103e257b25ae892cdede9a671366e8d4f3e51 Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Mon, 1 Jun 2026 23:58:17 -0600 Subject: [PATCH 3/5] Improve compile errors for unsupported functions When attempting to use a Ziglua function that is not supported for the target Lua version, the error message is now much more clear. Before error: root source file struct 'lua_all' has no member named 'lua_cpcall' After error: Lua.cProtectedCall() is not supported in Lua 5.5 Also cleans up documentation comments. Closes #210 --- src/lib.zig | 174 ++++++++++++++++++++++++++++++++++++-------------- src/tests.zig | 10 +-- 2 files changed, 130 insertions(+), 54 deletions(-) diff --git a/src/lib.zig b/src/lib.zig index 887743e..db5ba7f 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -839,6 +839,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_arith pub fn arith(lua: *Lua, op: ArithOperator) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); c.lua_arith(@ptrCast(lua), @intFromEnum(op)); } @@ -852,8 +853,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_atpanic pub fn atPanic(lua: *Lua, panic_fn: CFn) ?CFn { - if (lang == .luau) @compileError(@src().fn_name ++ " is not implemented in Luau."); - + comptime checkSupport(.{ .lua51, .lua52, .lua53, .lua54, .lua55, .luajit }, @src().fn_name); return c.lua_atpanic(@ptrCast(lua), panic_fn); } @@ -924,6 +924,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_callk pub fn callCont(lua: *Lua, args: CallContArgs) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55, }, @src().fn_name); c.lua_callk(@ptrCast(lua), args.args, args.results, args.ctx, args.k); } @@ -947,7 +948,7 @@ pub const Lua = opaque { /// marked to be closed (see `Lua.toClose()`) that is still active (that is, not closed yet). /// A `__close` metamethod cannot yield when called through this function. /// - /// Only implemented in Lua 5.4 + /// Only implemented in Lua 5.4 and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `0` @@ -955,6 +956,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_closeslot pub fn closeSlot(lua: *Lua, index: i32) void { + comptime checkSupport(.{ .lua54, .lua55 }, @src().fn_name); c.lua_closeslot(@ptrCast(lua), index); } @@ -973,6 +975,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_closethread pub fn closeThread(lua: *Lua, from: ?*Lua) error{CallError}!void { + comptime checkSupport(.{ .lua54, .lua55 }, @src().fn_name); if (c.lua_closethread(@ptrCast(lua), if (from) |f| @ptrCast(f) else null) != StatusCode.ok) return error.CallError; } @@ -990,6 +993,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_compare pub fn compare(lua: *Lua, index1: i32, index2: i32, op: CompareOperator) bool { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); return c.lua_compare(@ptrCast(lua), index1, index2, @intFromEnum(op)) != 0; } @@ -1012,7 +1016,7 @@ pub const Lua = opaque { /// containing `userdata`. In case of errors, `Lua.cProtectedCall()` returns the same error codes as `Lua.protectedCall()`, plus the error object on the /// top of the stack; otherwise, it returns zero, and does not change the stack. All values returned by `c_fn` are discarded. /// - /// Only implemented in Lua 5.1 and Luau. + /// Only implemented in Lua 5.1, Luau, and LuaJIT /// /// * Pops from Stack: `0` /// * Pushes to Stack: `(0|1)` @@ -1020,6 +1024,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.1/manual.html#lua_cpcall pub fn cProtectedCall(lua: *Lua, c_fn: CFn, userdata: *anyopaque) CProtectedCallError!void { + comptime checkSupport(.{ .lua51, .luau, .luajit }, @src().fn_name); const ret = c.lua_cpcall(@ptrCast(lua), c_fn, userdata); switch (ret) { StatusCode.ok => return, @@ -1041,6 +1046,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_copy pub fn copy(lua: *Lua, from_index: i32, to_index: i32) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); c.lua_copy(@ptrCast(lua), from_index, to_index); } @@ -1094,13 +1100,13 @@ pub const Lua = opaque { pub const dump = switch (lang) { .lua53, .lua54, .lua55 => dump53, else => dump51, - .luau => @compileError("Not implemented in Luau."), + .luau => @compileError("Lua.dump() is not supported in Luau"), }; /// Returns `true` if the two values in acceptable indices `index1` and `index2` are equal, following the semantics of the Lua `==` /// operator (that is, may call metamethods). Otherwise returns `false`. Also returns `false` if any of the indices is non valid. /// - /// Not implemented in Lua 5.2, 5.3, or 5.4 + /// Not implemented in Lua 5.2, 5.3, 5.4, or 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `0` @@ -1108,10 +1114,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.1/manual.html#lua_equal pub fn equal(lua: *Lua, index1: i32, index2: i32) bool { - switch (lang) { - .lua52, .lua53, .lua54, .lua55 => @compileError("lua_equal is deprecated, use Lua.compare with .eq instead"), - else => {}, - } + comptime checkSupport(.{ .lua51, .luau, .luajit }, @src().fn_name); return c.lua_equal(@ptrCast(lua), index1, index2) == 1; } @@ -1182,6 +1185,7 @@ pub const Lua = opaque { /// Returns a boolean that tells whether the garbage collector is running /// See https://www.lua.org/manual/5.4/manual.html#lua_gc pub fn gcIsRunning(lua: *Lua) bool { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55, .luau }, @src().fn_name); return switch (lang) { .lua54, .lua55 => c.lua_gc(@ptrCast(lua), c.LUA_GCISRUNNING) != 0, else => c.lua_gc(@ptrCast(lua), c.LUA_GCISRUNNING, 0) != 0, @@ -1192,6 +1196,7 @@ pub const Lua = opaque { /// Returns true if the previous mode was generational /// See https://www.lua.org/manual/5.4/manual.html#lua_gc pub fn gcSetIncremental(lua: *Lua, pause: i32, step_mul: i32, step_size: i32) bool { + comptime checkSupport(.{ .lua54, .lua55 }, @src().fn_name); return c.lua_gc(@ptrCast(lua), c.LUA_GCINC, pause, step_mul, step_size) == c.LUA_GCGEN; } @@ -1204,10 +1209,12 @@ pub const Lua = opaque { } pub fn gcSetGoal(lua: *Lua, goal: i32) i32 { + comptime checkSupport(.{ .luau }, @src().fn_name); return c.lua_gc(@ptrCast(lua), c.LUA_GCSETGOAL, goal); } pub fn gcSetStepSize(lua: *Lua, size: i32) i32 { + comptime checkSupport(.{ .luau }, @src().fn_name); return c.lua_gc(@ptrCast(lua), c.LUA_GCSETSTEPSIZE, size); } @@ -1217,13 +1224,14 @@ pub const Lua = opaque { pub const gcSetGenerational = switch (lang) { .lua52 => gcSetGenerational52, .lua54, .lua55 => gcSetGenerational54, - else => @compileError("gcSetGenerational() not available"), + else => @compileError("Lua.gcSetGenerational() is not supported in " ++ @tagName(lang)), }; /// Sets `pause` as the new value for the pause of the collector /// Returns the previous value of the pause /// See https://www.lua.org/manual/5.3/manual.html#lua_gc pub fn gcSetPause(lua: *Lua, pause: i32) i32 { + comptime checkSupport(.{ .lua51, .lua52, .lua53, .luajit }, @src().fn_name); return c.lua_gc(@ptrCast(lua), c.LUA_GCSETPAUSE, pause); } @@ -1231,6 +1239,7 @@ pub const Lua = opaque { /// Returns the previous value of the step multiplier /// See https://www.lua.org/manual/5.3/manual.html#lua_gc pub fn gcSetStepMul(lua: *Lua, multiplier: i32) i32 { + comptime checkSupport(.{ .lua51, .lua52, .lua53, .luajit, .luau }, @src().fn_name); return c.lua_gc(@ptrCast(lua), c.LUA_GCSETSTEPMUL, multiplier); } @@ -1254,6 +1263,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.2/manual.html#lua_getctx pub fn getContext(lua: *Lua, ctx: *i32) GetContextError!void { + comptime checkSupport(.{ .lua52 }, @src().fn_name); const ret = c.lua_getctx(@ptrCast(lua), ctx); switch (ret) { StatusCode.ok, StatusCode.yield => return, @@ -1269,7 +1279,7 @@ pub const Lua = opaque { /// /// This area has a size of a pointer to void /// - /// Only implemented in Lua 5.3 and 5.4 + /// Only implemented in Lua 5.3, 5.4, and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `0` @@ -1277,12 +1287,13 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_getextraspace pub fn getExtraSpace(lua: *Lua) []u8 { + comptime checkSupport(.{ .lua53, .lua54, .lua55 }, @src().fn_name); return @as([*]u8, @ptrCast(c.lua_getextraspace(@as(*LuaState, @ptrCast(lua))).?))[0..@sizeOf(isize)]; } /// Pushes onto the stack the environment table of the value at the given index. /// - /// Only implemented in Lua 5.1 and Luau + /// Only implemented in Lua 5.1, Luau, and LuaJIT /// /// * Pops from Stack: `0` /// * Pushes to Stack: `1` @@ -1290,6 +1301,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.1/manual.html#lua_getfenv pub fn getFnEnvironment(lua: *Lua, index: i32) void { + comptime checkSupport(.{ .lua51, .luau, .luajit }, @src().fn_name); c.lua_getfenv(@ptrCast(lua), index); } @@ -1337,7 +1349,7 @@ pub const Lua = opaque { /// /// Returns the type of the pushed value /// - /// Only implemented in Lua 5.3 and 5.4 + /// Only implemented in Lua 5.3, 5.4, and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `1` @@ -1345,6 +1357,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_geti pub fn getIndex(lua: *Lua, index: i32, i: Integer) LuaType { + comptime checkSupport(.{ .lua53, .lua54, .lua55 }, @src().fn_name); return @enumFromInt(c.lua_geti(@ptrCast(lua), index, i)); } @@ -1369,7 +1382,8 @@ pub const Lua = opaque { pub const getUserValue = switch (lang) { .lua53 => getUserValue53, .lua54, .lua55 => getUserValue54, - else => getUserValue52, + .lua52 => getUserValue52, + else => @compileError("Lua.getUserValue() is not supported in " ++ @tagName(lang)), }; /// If the value at the given index has a metatable, the function pushes that metatable onto the stack. @@ -1419,12 +1433,14 @@ pub const Lua = opaque { /// Only available in Luau pub fn setReadonly(lua: *Lua, idx: i32, enabled: bool) void { + comptime checkSupport(.{ .luau }, @src().fn_name); if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); c.lua_setreadonly(@ptrCast(lua), idx, @intFromBool(enabled)); } /// Only available in Luau pub fn getReadonly(lua: *Lua, idx: i32) bool { + comptime checkSupport(.{ .luau }, @src().fn_name); if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); return c.lua_getreadonly(@ptrCast(lua), idx) != 0; } @@ -1476,7 +1492,7 @@ pub const Lua = opaque { /// Returns true if the value at the given `index` is an integer /// - /// Only available in Lua 5.3 and 5.4 + /// Only available in Lua 5.3, 5.4, and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `0` @@ -1484,6 +1500,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_isinteger pub fn isInteger(lua: *Lua, index: i32) bool { + comptime checkSupport(.{ .lua53, .lua54, .lua55 }, @src().fn_name); return c.lua_isinteger(@ptrCast(lua), index) != 0; } @@ -1595,13 +1612,13 @@ pub const Lua = opaque { /// * Lua Runtime Errors: `none` /// pub fn isVector(lua: *Lua, index: i32) bool { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); return c.lua_isvector(@as(*LuaState, @ptrCast(lua)), index); } /// Returns true if the given coroutine can yield /// - /// Only available in Lua 5.3 and 5.4 + /// Only available in Lua 5.3, 5.4, and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `0` @@ -1609,6 +1626,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_isyieldable pub fn isYieldable(lua: *Lua) bool { + comptime checkSupport(.{ .lua53, .lua54, .lua55 }, @src().fn_name); return c.lua_isyieldable(@ptrCast(lua)) != 0; } @@ -1616,7 +1634,7 @@ pub const Lua = opaque { /// Equivalent to the # operator in Lua and may /// trigger a metamethod for the "length" event. The result is pushed on the stack. /// - /// Only implemented in Lua 5.2, 5.3, and 5.4 + /// Only implemented in Lua 5.2, 5.3, 5.4, and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `1` @@ -1624,6 +1642,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_len pub fn len(lua: *Lua, index: i32) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); c.lua_len(@ptrCast(lua), index); } @@ -1639,6 +1658,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_lessthan pub fn lessThan(lua: *Lua, index1: i32, index2: i32) bool { + comptime checkSupport(.{ .lua51, .luau, .luajit }, @src().fn_name); return c.lua_lessthan(@ptrCast(lua), index1, index2) == 1; } @@ -1646,7 +1666,7 @@ pub const Lua = opaque { .lua51, .luajit => error{ LuaSyntax, OutOfMemory }, .lua52, .lua53 => error{ LuaSyntax, OutOfMemory, LuaRuntime, LuaMsgHandler, LuaGCMetaMethod }, .lua54, .lua55 => error{ LuaSyntax, OutOfMemory, LuaRuntime, LuaMsgHandler }, - else => @compileError("Load not implemented in Luau"), + else => @compileError("Lua.load() is not supported in Luau"), }; fn load51(lua: *Lua, reader: CReaderFn, data: *anyopaque, chunk_name: [:0]const u8) LoadError!void { @@ -1773,6 +1793,7 @@ pub const Lua = opaque { }; pub fn newUserdataTagged(lua: *Lua, comptime T: type, tag: i32) *T { + comptime checkSupport(.{ .luau }, @src().fn_name); const UTAG_PROXY = c.LUA_UTAG_LIMIT + 1; // not exposed in headers std.debug.assert((tag >= 0 and tag < c.LUA_UTAG_LIMIT) or tag == UTAG_PROXY); // Luau will do the same assert, this is easier to debug // safe to .? because this function throws a Lua error on out of memory @@ -1786,6 +1807,7 @@ pub const Lua = opaque { /// /// Only available in Luau. pub fn getUserdataTag(lua: *Lua, index: i32) error{ExpectedTaggedUserdata}!i32 { + comptime checkSupport(.{ .luau }, @src().fn_name); const tag = c.lua_userdatatag(@ptrCast(lua), index); if (tag == -1) return error.ExpectedTaggedUserdata; return tag; @@ -1798,6 +1820,7 @@ pub const Lua = opaque { /// /// Note: Luau doesn't support the usual Lua __gc metatable destructor. Use this instead. pub fn newUserdataDtor(lua: *Lua, comptime T: type, dtor_fn: CUserdataDtorFn) *T { + comptime checkSupport(.{ .luau }, @src().fn_name); // safe to .? because this function throws a Lua error on out of memory // so the returned pointer should never be null const ptr = c.lua_newuserdatadtor(@ptrCast(lua), @sizeOf(T), @ptrCast(dtor_fn)).?; @@ -1826,10 +1849,11 @@ pub const Lua = opaque { /// it is converted to an integer and returned. If the integer is not in range, /// error.Overflow is returned. /// - /// Only available in Lua 5.4 and Lua 5.5. + /// Only available in Lua 5.3, 5.4, and 5.5. /// /// See https://www.lua.org/manual/5.4/manual.html#lua_numbertointeger pub fn numberToInteger(n: Number) error{Overflow}!Integer { + comptime checkSupport(.{ .lua53, .lua54, .lua55 }, @src().fn_name); // translate-c failure // return c.lua_numbertointeger(n, i) != 0; const min_float: Number = @floatFromInt(min_integer); @@ -1855,6 +1879,7 @@ pub const Lua = opaque { .luau => i32, else => usize, } { + comptime checkSupport(.{ .lua51, .luau, .luajit }, @src().fn_name); return c.lua_objlen(@ptrCast(lua), index); } @@ -1996,7 +2021,6 @@ pub const Lua = opaque { /// /// Any function to be callable by Lua must follow the correct protocol to receive its parameters and return its results. /// - /// /// When a C function is created, it is possible to associate some values with it, the so called upvalues; these upvalues /// are then accessible to the function whenever it is called. This association is called a C closure. To create /// a C closure, first the initial values for its upvalues must be pushed onto the stack. (When there are multiple @@ -2027,7 +2051,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_pushcclosure pub fn pushClosureNamed(lua: *Lua, c_fn: CFn, debugname: [:0]const u8, n: i32) void { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); c.lua_pushcclosurek(@ptrCast(lua), c_fn, debugname, n, null); } @@ -2051,7 +2075,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_pushcfunction pub fn pushFunctionNamed(lua: *Lua, c_fn: CFn, debugname: [:0]const u8) void { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); c.lua_pushcclosurek(@ptrCast(lua), c_fn, debugname, 0, null); } @@ -2088,7 +2112,7 @@ pub const Lua = opaque { /// Pushes the global environment onto the stack /// - /// Only implemented in Lua 5.2, 5.3 and 5.4 + /// Only implemented in Lua 5.2, 5.3, 5.4, and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `1` @@ -2096,6 +2120,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_pushglobaltable pub fn pushGlobalTable(lua: *Lua) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); // lua_pushglobaltable is a macro and c-translate assumes it returns opaque // so just reimplement the macro here // c.lua_pushglobaltable(@ptrCast(lua)); @@ -2218,6 +2243,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.2/manual.html#lua_pushunsigned pub fn pushUnsigned(lua: *Lua, n: Unsigned) void { + comptime checkSupport(.{ .lua52 }, @src().fn_name); return c.lua_pushunsigned(@ptrCast(lua), n); } @@ -2245,7 +2271,7 @@ pub const Lua = opaque { /// Only available in Luau pub const pushVector = switch (lang) { .luau => if (luau_vector_size == 3) pushVector3 else pushVector4, - else => @compileError("pushVector is only available in Luau."), + else => @compileError("Lua.pushVector() is only available in Luau"), }; /// Returns true if the two values in indices `index1` and `index2` are primitively equal @@ -2316,6 +2342,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_rawgetp pub fn getPtrRaw(lua: *Lua, index: i32, p: *const anyopaque) LuaType { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55, .luau }, @src().fn_name); switch (lang) { .lua53, .lua54, .lua55 => return @enumFromInt(c.lua_rawgetp(@ptrCast(lua), index, p)), .luau => return @enumFromInt(c.lua_rawgetp(@as(*LuaState, @ptrCast(lua)), index, @constCast(p))), @@ -2337,6 +2364,7 @@ pub const Lua = opaque { /// /// See https://sleitnick.github.io/luau-api/reference.html#lua_rawgetptagged pub fn getPtrRawTagged(lua: *Lua, index: i32, p: *const anyopaque, tag: i32) LuaType { + comptime checkSupport(.{ .luau }, @src().fn_name); return @enumFromInt(c.lua_rawgetptagged(@as(*LuaState, @ptrCast(lua)), index, @constCast(p), tag)); } @@ -2346,8 +2374,6 @@ pub const Lua = opaque { /// * for userdata, this is the size of the block of memory allocated for the userdata /// * For other values, this call returns 0. /// - /// Not available in Lua 5.1, LuaJIT or Luau - /// /// * Pops from Stack: `0` /// * Pushes to Stack: `0` /// * Lua Runtime Errors: `none` @@ -2396,6 +2422,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_rawsetp pub fn setPtrRaw(lua: *Lua, index: i32, p: *const anyopaque) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55, .luau }, @src().fn_name); switch (lang) { .luau => c.lua_rawsetp(@as(*LuaState, @ptrCast(lua)), index, @constCast(p)), else => c.lua_rawsetp(@ptrCast(lua), index, p), @@ -2416,6 +2443,7 @@ pub const Lua = opaque { /// /// See https://sleitnick.github.io/luau-api/reference.html#lua_rawsetptagged pub fn setPtrRawTagged(lua: *Lua, index: i32, p: *const anyopaque, tag: i32) void { + comptime checkSupport(.{ .luau }, @src().fn_name); c.lua_rawsetptagged(@as(*LuaState, @ptrCast(lua)), index, @constCast(p), tag); } @@ -2520,7 +2548,7 @@ pub const Lua = opaque { /// absolute value of `n` must not be greater than the size of the slice being rotated. This function cannot be called with a /// pseudo-index, because a pseudo-index is not an actual stack position. /// - /// Only available in Lua 5.3 and 5.4 + /// Only available in Lua 5.3, 5.4, and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `0` @@ -2528,6 +2556,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_rotate pub fn rotate(lua: *Lua, index: i32, n: i32) void { + comptime checkSupport(.{ .lua53, .lua54, .lua55 }, @src().fn_name); c.lua_rotate(@ptrCast(lua), index, n); } @@ -2542,6 +2571,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.1/manual.html#lua_setfenv pub fn setFnEnvironment(lua: *Lua, index: i32) error{InvalidValue}!void { + comptime checkSupport(.{ .lua51, .luau, .luajit }, @src().fn_name); if (c.lua_setfenv(@ptrCast(lua), index) == 0) return error.InvalidValue; } @@ -2654,7 +2684,7 @@ pub const Lua = opaque { /// /// Only available in Luau pub fn setUserdataTag(lua: *Lua, index: i32, tag: i32) void { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); std.debug.assert((tag >= 0 and tag < c.LUA_UTAG_LIMIT)); // Luau will do the same assert, this is easier to debug c.lua_setuserdatatag(@ptrCast(lua), index, tag); } @@ -2670,6 +2700,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_setwarnf pub fn setWarnF(lua: *Lua, warn_fn: CWarnFn, data: ?*anyopaque) void { + comptime checkSupport(.{ .lua54, .lua55 }, @src().fn_name); c.lua_setwarnf(@ptrCast(lua), warn_fn, data); } @@ -2696,6 +2727,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_stringtonumber pub fn stringToNumber(lua: *Lua, str: [:0]const u8) error{InvalidNumber}!void { + comptime checkSupport(.{ .lua53, .lua54, .lua55 }, @src().fn_name); const size = c.lua_stringtonumber(@ptrCast(lua), str.ptr); if (size == 0) return error.InvalidNumber; } @@ -2740,7 +2772,7 @@ pub const Lua = opaque { /// already unwound, so that any automatic C variable declared in the calling function (e.g., a buffer) will be out of /// scope. /// - /// Only available in Lua 5.4 + /// Only available in Lua 5.4 and 5.5 /// /// * Pops from Stack: `0` /// * Pushes to Stack: `0` @@ -2748,6 +2780,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_toclose pub fn toClose(lua: *Lua, index: i32) void { + comptime checkSupport(.{ .lua54, .lua55 }, @src().fn_name); c.lua_toclose(@ptrCast(lua), index); } @@ -2880,6 +2913,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.2/manual.html#lua_tounsignedx pub fn toUnsigned(lua: *Lua, index: i32) error{ExpectedNumber}!Unsigned { + comptime checkSupport(.{ .lua52 }, @src().fn_name); var success: c_int = undefined; const result = c.lua_tounsignedx(@ptrCast(lua), index, &success); if (success == 0) return error.ExpectedNumber; @@ -2922,7 +2956,7 @@ pub const Lua = opaque { /// Only available in Luau pub fn toUserdataTagged(lua: *Lua, comptime T: type, index: i32, tag: i32) error{ExpectedTaggedUserdata}!*T { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); if (c.lua_touserdatatagged(@ptrCast(lua), index, tag)) |ptr| return @ptrCast(@alignCast(ptr)); return error.ExpectedTaggedUserdata; } @@ -2932,7 +2966,7 @@ pub const Lua = opaque { /// /// Only available in Luau pub fn toVector(lua: *Lua, index: i32) error{ExpectedVector}![luau_vector_size]f32 { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); const res = c.lua_tovector(@ptrCast(lua), index); if (res) |r| { switch (luau_vector_size) { @@ -2949,7 +2983,7 @@ pub const Lua = opaque { /// /// Only available in Luau pub fn toStringAtom(lua: *Lua, index: i32) error{ExpectedString}!struct { i32, [:0]const u8 } { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); var length: usize = undefined; var atom: c_int = undefined; if (c.lua_tolstringatom(@ptrCast(lua), index, &length, &atom)) |ptr| { @@ -2963,7 +2997,7 @@ pub const Lua = opaque { /// /// Only available in Luau pub fn namecallAtom(lua: *Lua) error{ExpectedNamecall}!struct { i32, [:0]const u8 } { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); var atom: c_int = undefined; if (c.lua_namecallatom(@ptrCast(lua), &atom)) |ptr| { return .{ atom, std.mem.span(ptr) }; @@ -3031,7 +3065,8 @@ pub const Lua = opaque { /// See https://www.lua.org/manual/5.4/manual.html#lua_version pub const version = switch (lang) { .lua54, .lua55 => version54, - else => version52, + .lua52, .lua53 => version52, + else => @compileError("Lua.version() is not supported in " ++ @tagName(lang)), }; /// Emits a warning with the given `message` @@ -3045,6 +3080,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_warning pub fn warning(lua: *Lua, message: [:0]const u8, to_cont: bool) void { + comptime checkSupport(.{ .lua54, .lua55 }, @src().fn_name); c.lua_warning(@ptrCast(lua), message.ptr, @intFromBool(to_cont)); } @@ -3393,7 +3429,7 @@ pub const Lua = opaque { /// Only available in Luau pub fn setInterruptCallbackFn(lua: *Lua, cb: ?CInterruptCallbackFn) void { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); if (c.lua_callbacks(@ptrCast(lua))) |cb_struct| { cb_struct.*.interrupt = cb; } @@ -3401,7 +3437,7 @@ pub const Lua = opaque { /// Only available in Luau pub fn setUserAtomCallbackFn(lua: *Lua, cb: CUserAtomCallbackFn) void { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); if (c.lua_callbacks(@ptrCast(lua))) |cb_struct| { cb_struct.*.useratom = cb; } @@ -3422,6 +3458,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_upvalueid pub fn upvalueId(lua: *Lua, func_index: i32, n: i32) ?*anyopaque { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); return c.lua_upvalueid(@ptrCast(lua), func_index, n); } @@ -3436,6 +3473,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#lua_upvaluejoin pub fn upvalueJoin(lua: *Lua, func_index1: i32, n1: i32, func_index2: i32, n2: i32) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); c.lua_upvaluejoin(@ptrCast(lua), func_index1, n1, func_index2, n2); } @@ -3677,7 +3715,7 @@ pub const Lua = opaque { /// /// Only available in Luau pub fn checkVector(lua: *Lua, arg: i32) [luau_vector_size]f32 { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); const vec = lua.toVector(arg) catch { lua.typeError(arg, lua.typeName(LuaType.vector)); }; @@ -3704,7 +3742,8 @@ pub const Lua = opaque { /// See https://www.lua.org/manual/5.4/manual.html#luaL_checkversion pub const checkVersion = switch (lang) { .lua53, .lua54, .lua55 => checkVersion53, - else => checkVersion52, + .lua52 => checkVersion52, + else => @compileError("Lua.checkVersion() is not supported in " ++ @tagName(lang)), }; const DoFileError = LoadFileError || CallError; @@ -3717,6 +3756,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_dofile pub fn doFile(lua: *Lua, file_name: [:0]const u8) DoFileError!void { + comptime checkSupport(.{ .lua51, .lua52, .lua53, .lua54, .lua55, .luajit }, @src().fn_name); // translate-c failure switch (lang) { .luajit, .lua51 => try lua.loadFile(file_name), @@ -3761,7 +3801,7 @@ pub const Lua = opaque { /// /// Only available in Luau pub fn raiseInterruptErrorStr(lua: *Lua, fmt: [:0]const u8, args: anytype) noreturn { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); c.lua_rawcheckstack(@ptrCast(lua), 1); lua.raiseErrorStr(fmt, args); unreachable; @@ -3777,6 +3817,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_execresult pub fn execResult(lua: *Lua, stat: i32) i32 { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); return c.luaL_execresult(@ptrCast(lua), stat); } @@ -3791,6 +3832,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_fileresult pub fn fileResult(lua: *Lua, stat: i32, file_name: [:0]const u8) i32 { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); return c.luaL_fileresult(@ptrCast(lua), stat, file_name.ptr); } @@ -3837,6 +3879,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_getsubtable pub fn getSubtable(lua: *Lua, index: i32, field: [:0]const u8) bool { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); return c.luaL_getsubtable(@ptrCast(lua), index, field.ptr) != 0; } @@ -3851,7 +3894,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_gsub pub fn globalSub(lua: *Lua, str: [:0]const u8, pat: [:0]const u8, rep: [:0]const u8) []const u8 { - if (lang == .luau) @compileError(@src().fn_name ++ " is not available in Luau."); + comptime checkSupport(.{ .lua51, .lua52, .lua53, .lua54, .lua55, .luajit }, @src().fn_name); const s = c.luaL_gsub(@ptrCast(lua), str.ptr, pat.ptr, rep.ptr); const l = lua.lenRaw(-1); return s[0..l]; @@ -3991,6 +4034,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_newlib pub fn newLib(lua: *Lua, list: []const FnReg) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); // translate-c failure lua.checkVersion(); lua.newLibTable(list); @@ -4008,6 +4052,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_newlibtable pub fn newLibTable(lua: *Lua, list: []const FnReg) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); // translate-c failure lua.createTable(0, @intCast(list.len)); } @@ -4079,6 +4124,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.2/manual.html#luaL_optunsigned pub fn optUnsigned(lua: *Lua, arg: i32) ?Unsigned { + comptime checkSupport(.{ .lua52 }, @src().fn_name); if (lua.isNoneOrNil(arg)) return null; return lua.checkUnsigned(arg); } @@ -4093,6 +4139,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_pushfail pub fn pushFail(lua: *Lua) void { + comptime checkSupport(.{ .lua54, .lua55 }, @src().fn_name); c.luaL_pushfail(@as(*LuaState, @ptrCast(lua))); } @@ -4139,6 +4186,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.1/manual.html#luaL_register pub fn registerFns(lua: *Lua, libname: ?[:0]const u8, funcs: []const FnReg) void { + comptime checkSupport(.{ .lua51, .luau, .luajit }, @src().fn_name); // translated from the implementation of luaI_openlib so we can use a slice of // FnReg without requiring a sentinel end value if (libname) |name| { @@ -4206,6 +4254,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_setfuncs pub fn setFuncs(lua: *Lua, funcs: []const FnReg, num_upvalues: i32) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); lua.checkStackErr(num_upvalues, "too many upvalues"); for (funcs) |f| { if (f.func) |func| { @@ -4230,6 +4279,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_setmetatable pub fn setMetatableRegistry(lua: *Lua, table_name: [:0]const u8) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); c.luaL_setmetatable(@ptrCast(lua), table_name.ptr); } @@ -4243,6 +4293,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_testudata pub fn testUserdata(lua: *Lua, comptime T: type, arg: i32, name: [:0]const u8) error{ExpectedUserdata}!*T { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); if (c.luaL_testudata(@ptrCast(lua), arg, name.ptr)) |ptr| { return @ptrCast(@alignCast(ptr)); } else return error.ExpectedUserdata; @@ -4258,6 +4309,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_checkudata pub fn testUserdataSlice(lua: *Lua, comptime T: type, arg: i32, name: [:0]const u8) error{ExpectedUserdata}![]T { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); if (c.luaL_testudata(@ptrCast(lua), arg, name.ptr)) |ptr| { const size = lua.lenRaw(arg) / @sizeOf(T); return @as([*]T, @ptrCast(@alignCast(ptr)))[0..size]; @@ -4275,6 +4327,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_tolstring pub fn toStringEx(lua: *Lua, index: i32) [:0]const u8 { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55 }, @src().fn_name); var length: usize = undefined; const ptr = c.luaL_tolstring(@ptrCast(lua), index, &length); return ptr[0..length :0]; @@ -4304,6 +4357,7 @@ pub const Lua = opaque { /// /// See https://www.lua.org/manual/5.4/manual.html#luaL_typeerror pub fn typeError(lua: *Lua, arg: i32, type_name: [:0]const u8) noreturn { + comptime checkSupport(.{ .lua54, .lua55, .luau }, @src().fn_name); _ = c.luaL_typeerror(@as(*LuaState, @ptrCast(lua)), arg, type_name.ptr); unreachable; } @@ -4391,6 +4445,7 @@ pub const Lua = opaque { /// * Pushes to Stack: `0` /// * Lua Runtime Errors: `any` pub fn openCoroutine(lua: *Lua) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55, .luau }, @src().fn_name); lua.requireF(c.LUA_COLIBNAME, c.luaopen_coroutine, true); if (lang == .lua52 or lang == .lua53 or lang == .lua54 or lang == .lua55) lua.pop(1); } @@ -4403,7 +4458,7 @@ pub const Lua = opaque { /// * Pushes to Stack: `0` /// * Lua Runtime Errors: `any` pub fn openPackage(lua: *Lua) void { - if (lang == .luau) @compileError(@src().fn_name ++ " is not available in Luau."); + comptime checkSupport(.{ .lua51, .lua52, .lua53, .lua54, .lua55, .luajit }, @src().fn_name); lua.requireF(c.LUA_LOADLIBNAME, c.luaopen_package, true); if (lang == .lua52 or lang == .lua53 or lang == .lua54 or lang == .lua55) lua.pop(1); } @@ -4426,6 +4481,7 @@ pub const Lua = opaque { /// * Pushes to Stack: `0` /// * Lua Runtime Errors: `any` pub fn openUtf8(lua: *Lua) void { + comptime checkSupport(.{ .lua52, .lua53, .lua54, .lua55, .luau }, @src().fn_name); lua.requireF(c.LUA_UTF8LIBNAME, c.luaopen_utf8, true); if (lang == .lua52 or lang == .lua53 or lang == .lua54 or lang == .lua55) lua.pop(1); } @@ -4458,7 +4514,7 @@ pub const Lua = opaque { /// * Pushes to Stack: `0` /// * Lua Runtime Errors: `any` pub fn openIO(lua: *Lua) void { - if (lang == .luau) @compileError(@src().fn_name ++ " is not available in Luau."); + comptime checkSupport(.{ .lua51, .lua52, .lua53, .lua54, .lua55, .luajit }, @src().fn_name); lua.requireF(c.LUA_IOLIBNAME, c.luaopen_io, true); if (lang == .lua52 or lang == .lua53 or lang == .lua54 or lang == .lua55) lua.pop(1); } @@ -4491,12 +4547,13 @@ pub const Lua = opaque { /// * Pushes to Stack: `0` /// * Lua Runtime Errors: `any` pub fn openBit32(lua: *Lua) void { + comptime checkSupport(.{ .lua52, .luajit }, @src().fn_name); switch (lang) { - .lua52, .lua53 => lua.requireF(c.LUA_BITLIBNAME, c.luaopen_bit32, true), + .lua52 => lua.requireF(c.LUA_BITLIBNAME, c.luaopen_bit32, true), .luajit => lua.requireF(c.LUA_BITLIBNAME, c.luaopen_bit, true), - else => @compileError(@src().fn_name ++ " is only available in Lua 5.2 and LuaJIT."), + else => unreachable, } - // For some reason Lua 5.2 leaves a value on the stack. + // For some reason only Lua 5.2 leaves a value on the stack. if (lang == .lua52) lua.pop(1); } pub const openBit = openBit32; @@ -4509,7 +4566,7 @@ pub const Lua = opaque { /// * Pushes to Stack: `0` /// * Lua Runtime Errors: `any` pub fn openVector(lua: *Lua) void { - if (lang != .luau) @compileError(@src().fn_name ++ " is only available in Luau."); + comptime checkSupport(.{ .luau }, @src().fn_name); lua.requireF(c.LUA_VECLIBNAME, c.luaopen_vector, true); } @@ -5456,7 +5513,7 @@ pub fn wrap(comptime function: anytype) TypeOfWrap(function) { return -1; } }.inner, - CWarnFn => if (lang != .lua54) @compileError("CWarnFn is only valid in Lua >= 5.4") else struct { + CWarnFn => if (lang != .lua54 and lang != .lua55) @compileError("CWarnFn is only valid in Lua >= 5.4") else struct { fn inner(data: ?*anyopaque, msg: [*c]const u8, to_cont: c_int) callconv(.c) void { // warning messages emitted from Lua should be null-terminated for display const message = std.mem.span(@as([*:0]const u8, @ptrCast(msg))); @@ -5613,3 +5670,22 @@ pub fn fnRegsFromType(comptime T: type) []const FnReg { const final = funcs; return final; } + +fn checkSupport(versions: anytype, fn_name: []const u8) void { + const supported = blk: { + inline for (versions) |version| if (lang == version) break :blk true; + break :blk false; + }; + if (!supported) { + const name = switch (lang) { + .lua51 => "Lua 5.1", + .lua52 => "Lua 5.2", + .lua53 => "Lua 5.3", + .lua54 => "Lua 5.4", + .lua55 => "Lua 5.5", + .luau => "Luau", + .luajit => "LuaJIT", + }; + @compileError("Lua." ++ fn_name ++ "() is not supported in " ++ name); + } +} diff --git a/src/tests.zig b/src/tests.zig index 6aa7d9b..66fb009 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -449,7 +449,7 @@ test "calling a function" { } test "calling a function with cProtectedCall" { - if (zlua.lang != .lua51 and zlua.lang != .luau) return; + if (zlua.lang != .lua51 and zlua.lang != .luau and zlua.lang != .luajit) return; const lua: *Lua = try .init(testing.allocator); defer lua.deinit(); @@ -670,7 +670,7 @@ test "panic fn" { } test "warn fn" { - if (zlua.lang != .lua54) return; + if (zlua.lang != .lua54 and zlua.lang != .lua55) return; const lua: *Lua = try .init(testing.allocator); defer lua.deinit(); @@ -720,7 +720,7 @@ test "garbage collector" { if (zlua.lang != .lua51 and zlua.lang != .luajit) _ = lua.gcIsRunning(); - if (langIn(.{ .lua51, .lua52, .lua53 })) { + if (langIn(.{ .lua51, .lua52, .lua53, .luajit })) { _ = lua.gcSetPause(2); _ = lua.gcSetStepMul(2); } @@ -1063,7 +1063,7 @@ test "registry" { } test "closing vars" { - if (zlua.lang != .lua54) return; + if (zlua.lang != .lua54 and zlua.lang != .lua55) return; const lua: *Lua = try .init(testing.allocator); defer lua.deinit(); @@ -1798,7 +1798,7 @@ test "function environments" { } test "objectLen" { - if (zlua.lang != .lua51 and zlua.lang != .luau) return; + if (zlua.lang != .lua51 and zlua.lang != .luau and zlua.lang != .luajit) return; const lua: *Lua = try .init(testing.allocator); defer lua.deinit(); From 2f0f668a9a7e7d4ab5d90853958837bae5bc3ca2 Mon Sep 17 00:00:00 2001 From: Rawan10101 Date: Mon, 8 Jun 2026 09:55:29 +0300 Subject: [PATCH 4/5] build: add -flto for wasm32 to fix setjmp/longjmp with Emscripten --- build/lua.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build/lua.zig b/build/lua.zig index f89f771..5588d0f 100644 --- a/build/lua.zig +++ b/build/lua.zig @@ -75,6 +75,7 @@ pub fn configure( if (target.result.os.tag == .windows and shared) "-DLUA_BUILD_AS_DLL" else "", if (lua_user_h) |_| b.fmt("-DLUA_USER_H=\"{s}\"", .{user_header}) else "", + if (target.result.cpu.arch == .wasm32) "-flto" else "", }; const lua_source_files = switch (lang) { From 9a520d0bbaac378d2e926c76edb584da104941dc Mon Sep 17 00:00:00 2001 From: robin Date: Mon, 8 Jun 2026 12:36:09 +0200 Subject: [PATCH 5/5] Additional system headers as slice of LazyPath --- build.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index 9444150..7025dfd 100644 --- a/build.zig +++ b/build.zig @@ -41,7 +41,7 @@ pub fn build(b: *Build) void { const system_lua = b.option(bool, "system_lua", "Use system lua") orelse false; const luau_use_4_vector = b.option(bool, "luau_use_4_vector", "Build Luau to use 4-vectors instead of the default 3-vector.") orelse false; const lua_user_h = b.option(Build.LazyPath, "lua_user_h", "Lazy path to user supplied c header file") orelse null; - const additional_system_headers = b.option(Build.LazyPath, "additional_system_headers", "Lazy path to additional system headers to include when building Lua") orelse null; + const additional_system_headers = b.option([]Build.LazyPath, "additional_system_headers", "Slice of Lazy paths to additional system headers to include when building Lua") orelse null; const api_check = b.option(ApiCheck, "apicheck", "Enable parameter checks in the Lua API") orelse .debug; if (lang == .luau and shared) { @@ -87,9 +87,9 @@ pub fn build(b: *Build) void { // If we've been given additional system headers, add them now. // Useful for things like linking Emscripten headers by including a new sysroot - if (additional_system_headers) |headers| { - t.addSystemIncludePath(headers); - } + if (additional_system_headers) |include_paths| for (include_paths) |include_path| { + t.addSystemIncludePath(include_path); + }; zlua.addImport("c", t.mod);