From a7b78d919fa93e4d2aabcdebe0e638753a3f76ae Mon Sep 17 00:00:00 2001 From: Nathan Craddock Date: Wed, 22 Feb 2023 20:09:00 -0700 Subject: [PATCH] feat: update docs for 5.2 api Also renames a few functions, adds a few missing functions --- src/ziglua-5.1/lib.zig | 1 + src/ziglua-5.2/lib.zig | 296 ++++++++++++++++++++++++++++----------- src/ziglua-5.2/tests.zig | 18 +-- 3 files changed, 226 insertions(+), 89 deletions(-) diff --git a/src/ziglua-5.1/lib.zig b/src/ziglua-5.1/lib.zig index c577448..c22e3a6 100644 --- a/src/ziglua-5.1/lib.zig +++ b/src/ziglua-5.1/lib.zig @@ -1481,6 +1481,7 @@ pub const Buffer = struct { b: LuaBuffer = undefined, /// Initialize a Lua string buffer + /// See https://www.lua.org/manual/5.1/manual.html#luaL_buffinit pub fn init(buf: *Buffer, lua: Lua) void { c.luaL_buffinit(lua.state, &buf.b); } diff --git a/src/ziglua-5.2/lib.zig b/src/ziglua-5.2/lib.zig index 3a48b00..d1811f1 100644 --- a/src/ziglua-5.2/lib.zig +++ b/src/ziglua-5.2/lib.zig @@ -20,7 +20,7 @@ const Allocator = std.mem.Allocator; /// `data` is an opaque pointer to any data (the allocator), `ptr` is a pointer to the block being alloced/realloced/freed /// `osize` is the original size or a code, and `nsize` is the new size /// -/// See https://www.lua.org/manual/5.4/manual.html#lua_Alloc for more details +/// See https://www.lua.org/manual/5.2/manual.html#lua_Alloc for more details pub const AllocFn = *const fn (data: ?*anyopaque, ptr: ?*anyopaque, osize: usize, nsize: usize) callconv(.C) ?*anyopaque; /// Operations supported by `Lua.arith()` @@ -35,7 +35,7 @@ pub const ArithOperator = enum(u4) { }; /// Type for C functions -/// See https://www.lua.org/manual/5.4/manual.html#lua_CFunction for the protocol +/// See https://www.lua.org/manual/5.2/manual.html#lua_CFunction for the protocol pub const CFn = *const fn (state: ?*LuaState) callconv(.C) c_int; /// Operations supported by `Lua.compare()` @@ -297,7 +297,7 @@ pub const Lua = struct { const alignment = @alignOf(std.c.max_align_t); /// Allows Lua to allocate memory using a Zig allocator passed in via data. - /// See https://www.lua.org/manual/5.4/manual.html#lua_Alloc for more details + /// See https://www.lua.org/manual/5.2/manual.html#lua_Alloc for more details fn alloc(data: ?*anyopaque, ptr: ?*anyopaque, osize: usize, nsize: usize) callconv(.C) ?*align(alignment) anyopaque { // just like malloc() returns a pointer "which is suitably aligned for any built-in type", // the memory allocated by this function should also be aligned for any type that Lua may @@ -355,21 +355,21 @@ pub const Lua = struct { // Each is kept similar to the original C API function while also making it easy to use from Zig /// Returns the acceptable index index converted into an equivalent absolute index - /// See https://www.lua.org/manual/5.4/manual.html#lua_absindex + /// See https://www.lua.org/manual/5.2/manual.html#lua_absindex pub fn absIndex(lua: *Lua, index: i32) i32 { return c.lua_absindex(lua.state, index); } - /// Performs an arithmetic or bitwise operation over the value(s) at the top of the stack, + /// Performs an arithmetic operation over the value(s) at the top of the stack, /// with the value at the top being the second operand. Pushes the result of the operation. /// This function follows the semantics of the corresponding Lua operator and may call metamethods - /// See https://www.lua.org/manual/5.4/manual.html#lua_arith + /// See https://www.lua.org/manual/5.2/manual.html#lua_arith pub fn arith(lua: *Lua, op: ArithOperator) void { c.lua_arith(lua.state, @enumToInt(op)); } /// Sets a new panic function and returns the old one - /// See https://www.lua.org/manual/5.4/manual.html#lua_atpanic + /// See https://www.lua.org/manual/5.2/manual.html#lua_atpanic pub fn atPanic(lua: *Lua, panic_fn: CFn) ?CFn { return c.lua_atpanic(lua.state, panic_fn); } @@ -378,13 +378,13 @@ pub const Lua = struct { /// First push the function to be called onto the stack. Then push any arguments onto the stack. /// Then call this function. All arguments and the function value are popped, and any results /// are pushed onto the stack. - /// See https://www.lua.org/manual/5.4/manual.html#lua_call + /// See https://www.lua.org/manual/5.2/manual.html#lua_call pub fn call(lua: *Lua, num_args: i32, num_results: i32) void { lua.callCont(num_args, num_results, 0, null); } /// Like call, but allows the called function to yield - /// See https://www.lua.org/manual/5.4/manual.html#lua_callk + /// See https://www.lua.org/manual/5.2/manual.html#lua_callk pub fn callCont(lua: *Lua, num_args: i32, num_results: i32, ctx: i32, k: ?CFn) void { c.lua_callk(lua.state, num_args, num_results, ctx, k); } @@ -392,13 +392,13 @@ pub const Lua = struct { /// Ensures that the stack has space for at least n extra arguments /// Returns an error if more stack space cannot be allocated /// Never shrinks the stack - /// See https://www.lua.org/manual/5.4/manual.html#lua_checkstack + /// See https://www.lua.org/manual/5.2/manual.html#lua_checkstack pub fn checkStack(lua: *Lua, n: i32) !void { if (c.lua_checkstack(lua.state, n) == 0) return error.Fail; } /// Release all Lua objects in the state and free all dynamic memory - /// See https://www.lua.org/manual/5.4/manual.html#lua_close + /// See https://www.lua.org/manual/5.2/manual.html#lua_close pub fn close(lua: *Lua) void { c.lua_close(lua.state); } @@ -406,7 +406,7 @@ pub const Lua = struct { /// Compares two Lua values /// Returns true if the value at index1 satisisfies the comparison with the value at index2 /// Returns false otherwise, or if any index is not valid - /// See https://www.lua.org/manual/5.4/manual.html#lua_compare + /// See https://www.lua.org/manual/5.2/manual.html#lua_compare pub fn compare(lua: *Lua, index1: i32, index2: i32, op: CompareOperator) bool { // TODO: perhaps support gt/ge by swapping args... return c.lua_compare(lua.state, index1, index2, @enumToInt(op)) != 0; @@ -415,13 +415,13 @@ pub const Lua = struct { /// Concatenates the n values at the top of the stack, pops them, and leaves the result at the top /// If the number of values is 1, the result is a single value on the stack (nothing changes) /// If the number of values is 0, the result is the empty string - /// See https://www.lua.org/manual/5.4/manual.html#lua_concat + /// See https://www.lua.org/manual/5.2/manual.html#lua_concat pub fn concat(lua: *Lua, n: i32) void { c.lua_concat(lua.state, n); } /// Copies the element at from_index to the valid index to_index, replacing the value at that position - /// See https://www.lua.org/manual/5.4/manual.html#lua_copy + /// See https://www.lua.org/manual/5.2/manual.html#lua_copy pub fn copy(lua: *Lua, from_index: i32, to_index: i32) void { c.lua_copy(lua.state, from_index, to_index); } @@ -430,7 +430,7 @@ pub const Lua = struct { /// num_arr is a hint for how many elements the table will have as a sequence /// num_rec is a hint for how many other elements the table will have /// Lua may preallocate memory for the table based on the hints - /// See https://www.lua.org/manual/5.4/manual.html#lua_createtable + /// See https://www.lua.org/manual/5.2/manual.html#lua_createtable pub fn createTable(lua: *Lua, num_arr: i32, num_rec: i32) void { c.lua_createtable(lua.state, num_arr, num_rec); } @@ -438,85 +438,99 @@ pub const Lua = struct { /// Dumps a function as a binary chunk /// Data is a pointer passed to the writer function /// Returns an error if writing was unsuccessful - /// See https://www.lua.org/manual/5.4/manual.html#lua_dump + /// See https://www.lua.org/manual/5.2/manual.html#lua_dump pub fn dump(lua: *Lua, writer: CWriterFn, data: *anyopaque) !void { if (c.lua_dump(lua.state, writer, data) != 0) return error.Fail; } /// Raises a Lua error using the value at the top of the stack as the error object /// Does a longjump and therefore never returns - /// See https://www.lua.org/manual/5.4/manual.html#lua_error + /// See https://www.lua.org/manual/5.2/manual.html#lua_error pub fn raiseError(lua: *Lua) noreturn { _ = c.lua_error(lua.state); unreachable; } /// Perform a full garbage-collection cycle - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc pub fn gcCollect(lua: *Lua) void { _ = c.lua_gc(lua.state, c.LUA_GCCOLLECT, 0); } /// Stops the garbage collector - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc pub fn gcStop(lua: *Lua) void { _ = c.lua_gc(lua.state, c.LUA_GCSTOP, 0); } /// Restarts the garbage collector - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc pub fn gcRestart(lua: *Lua) void { _ = c.lua_gc(lua.state, c.LUA_GCRESTART, 0); } /// Performs an incremental step of garbage collection corresponding to the allocation of step_size Kbytes - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc pub fn gcStep(lua: *Lua) void { _ = c.lua_gc(lua.state, c.LUA_GCSTEP, 0); } /// Returns the current amount of memory (in Kbytes) in use by Lua - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc pub fn gcCount(lua: *Lua) i32 { return c.lua_gc(lua.state, c.LUA_GCCOUNT, 0); } /// Returns the remainder of dividing the current amount of bytes of memory in use by Lua by 1024 - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc pub fn gcCountB(lua: *Lua) i32 { return c.lua_gc(lua.state, c.LUA_GCCOUNTB, 0); } /// Returns a boolean that tells whether the garbage collector is running - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc pub fn gcIsRunning(lua: *Lua) bool { return c.lua_gc(lua.state, c.LUA_GCISRUNNING, 0) != 0; } - /// Changes the collector to incremental mode - /// Returns true if the previous mode was generational - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// 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.2/manual.html#lua_gc pub fn gcSetPause(lua: *Lua, pause: i32) i32 { return c.lua_gc(lua.state, c.LUA_GCSETPAUSE, pause); } - /// Changes the collector to generational mode - /// Returns true if the previous mode was incremental - /// See https://www.lua.org/manual/5.4/manual.html#lua_gc + /// Sets `multiplier` as the new value for the step multiplier of the collector + /// Returns the previous value of the step multiplier + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc pub fn gcSetStepMul(lua: *Lua, multiplier: i32) i32 { return c.lua_gc(lua.state, c.LUA_GCSETSTEPMUL, multiplier); } + /// Changes the collector to generational mode + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc + pub fn gcSetGenerational(lua: *Lua) void { + _ = c.lua_gc(lua.state, c.LUA_GCGEN, 0); + } + + /// Changes the collector to incremental mode. This is the default mode + /// See https://www.lua.org/manual/5.2/manual.html#lua_gc + pub fn gcSetIncremental(lua: *Lua) void { + _ = c.lua_gc(lua.state, c.LUA_GCINC, 0); + } + /// Returns the memory allocation function of a given state /// If data is not null, it is set to the opaque pointer given when the allocator function was set - /// See https://www.lua.org/manual/5.4/manual.html#lua_getallocf + /// See https://www.lua.org/manual/5.2/manual.html#lua_getallocf pub fn getAllocFn(lua: *Lua, data: ?**anyopaque) AllocFn { // Assert cannot be null because it is impossible (and not useful) to pass null // to the functions that set the allocator (setallocf and newstate) return c.lua_getallocf(lua.state, @ptrCast([*c]?*anyopaque, data)).?; } - pub fn getCtx(lua: *Lua) !?i32 { + /// Called by a continuation function to retrieve the status of the thread and context information + /// See https://www.lua.org/manual/5.2/manual.html#lua_getctx + pub fn getContext(lua: *Lua) !?i32 { var ctx: i32 = undefined; const ret = c.lua_getctx(lua.state, &ctx); switch (ret) { @@ -530,134 +544,131 @@ pub const Lua = struct { } /// Pushes onto the stack the value t[key] where t is the value at the given index - /// See https://www.lua.org/manual/5.4/manual.html#lua_getfield + /// See https://www.lua.org/manual/5.2/manual.html#lua_getfield pub fn getField(lua: *Lua, index: i32, key: [:0]const u8) void { c.lua_getfield(lua.state, index, key.ptr); } /// Pushes onto the stack the value of the global name - /// See https://www.lua.org/manual/5.4/manual.html#lua_getglobal + /// See https://www.lua.org/manual/5.2/manual.html#lua_getglobal pub fn getGlobal(lua: *Lua, name: [:0]const u8) void { c.lua_getglobal(lua.state, name.ptr); } /// Pushes onto the stack the Lua value associated with the full userdata at the given index. - /// Returns the type of the pushed value. - /// See https://www.lua.org/manual/5.3/manual.html#lua_getuservalue + /// See https://www.lua.org/manual/5.2/manual.html#lua_getuservalue pub fn getUserValue(lua: *Lua, index: i32) void { c.lua_getuservalue(lua.state, index); } /// If the value at the given index has a metatable, the function pushes that metatable onto the stack /// Otherwise an error is returned - /// See https://www.lua.org/manual/5.4/manual.html#lua_getmetatable + /// See https://www.lua.org/manual/5.2/manual.html#lua_getmetatable pub fn getMetatable(lua: *Lua, index: i32) !void { if (c.lua_getmetatable(lua.state, index) == 0) return error.Fail; } /// Pushes onto the stack the value t[k] where t is the value at the given index and k is the value on the top of the stack - /// Returns the type of the pushed value - /// See https://www.lua.org/manual/5.4/manual.html#lua_gettable + /// See https://www.lua.org/manual/5.2/manual.html#lua_gettable pub fn getTable(lua: *Lua, index: i32) void { c.lua_gettable(lua.state, index); } /// Returns the index of the top element in the stack /// Because indices start at 1, the result is also equal to the number of elements in the stack - /// See https://www.lua.org/manual/5.4/manual.html#lua_gettop + /// See https://www.lua.org/manual/5.2/manual.html#lua_gettop pub fn getTop(lua: *Lua) i32 { return c.lua_gettop(lua.state); } /// Moves the top element into the given valid `index` shifting up any elements to make room - /// See https://www.lua.org/manual/5.4/manual.html#lua_insert + /// See https://www.lua.org/manual/5.2/manual.html#lua_insert pub fn insert(lua: *Lua, index: i32) void { - // translate-c cannot translate this macro correctly c.lua_insert(lua.state, index); } /// Returns true if the value at the given index is a boolean - /// See https://www.lua.org/manual/5.4/manual.html#lua_isboolean + /// See https://www.lua.org/manual/5.2/manual.html#lua_isboolean pub fn isBoolean(lua: *Lua, index: i32) bool { return c.lua_isboolean(lua.state, index); } /// Returns true if the value at the given index is a CFn - /// See https://www.lua.org/manual/5.4/manual.html#lua_iscfunction + /// See https://www.lua.org/manual/5.2/manual.html#lua_iscfunction pub fn isCFunction(lua: *Lua, index: i32) bool { return c.lua_iscfunction(lua.state, index) != 0; } /// Returns true if the value at the given index is a function (C or Lua) - /// See https://www.lua.org/manual/5.4/manual.html#lua_isfunction + /// See https://www.lua.org/manual/5.2/manual.html#lua_isfunction pub fn isFunction(lua: *Lua, index: i32) bool { return c.lua_isfunction(lua.state, index); } /// Returns true if the value at the given index is a light userdata - /// See https://www.lua.org/manual/5.4/manual.html#lua_islightuserdata + /// See https://www.lua.org/manual/5.2/manual.html#lua_islightuserdata pub fn isLightUserdata(lua: *Lua, index: i32) bool { return c.lua_islightuserdata(lua.state, index); } /// Returns true if the value at the given index is nil - /// See https://www.lua.org/manual/5.4/manual.html#lua_isnil + /// See https://www.lua.org/manual/5.2/manual.html#lua_isnil pub fn isNil(lua: *Lua, index: i32) bool { return c.lua_isnil(lua.state, index); } /// Returns true if the given index is not valid - /// See https://www.lua.org/manual/5.4/manual.html#lua_isnone + /// See https://www.lua.org/manual/5.2/manual.html#lua_isnone pub fn isNone(lua: *Lua, index: i32) bool { return c.lua_isnone(lua.state, index); } /// Returns true if the given index is not valid or if the value at the index is nil - /// See https://www.lua.org/manual/5.4/manual.html#lua_isnoneornil + /// See https://www.lua.org/manual/5.2/manual.html#lua_isnoneornil pub fn isNoneOrNil(lua: *Lua, index: i32) bool { return c.lua_isnoneornil(lua.state, index); } /// Returns true if the value at the given index is a number - /// See https://www.lua.org/manual/5.4/manual.html#lua_isnumber + /// See https://www.lua.org/manual/5.2/manual.html#lua_isnumber pub fn isNumber(lua: *Lua, index: i32) bool { return c.lua_isnumber(lua.state, index) != 0; } /// Returns true if the value at the given index is a string - /// See https://www.lua.org/manual/5.4/manual.html#lua_isstring + /// See https://www.lua.org/manual/5.2/manual.html#lua_isstring pub fn isString(lua: *Lua, index: i32) bool { return c.lua_isstring(lua.state, index) != 0; } /// Returns true if the value at the given index is a table - /// See https://www.lua.org/manual/5.4/manual.html#lua_istable + /// See https://www.lua.org/manual/5.2/manual.html#lua_istable pub fn isTable(lua: *Lua, index: i32) bool { return c.lua_istable(lua.state, index); } /// Returns true if the value at the given index is a thread - /// See https://www.lua.org/manual/5.4/manual.html#lua_isthread + /// See https://www.lua.org/manual/5.2/manual.html#lua_isthread pub fn isThread(lua: *Lua, index: i32) bool { return c.lua_isthread(lua.state, index); } /// Returns true if the value at the given index is a userdata (full or light) - /// See https://www.lua.org/manual/5.4/manual.html#lua_isuserdata + /// See https://www.lua.org/manual/5.2/manual.html#lua_isuserdata pub fn isUserdata(lua: *Lua, index: i32) bool { return c.lua_isuserdata(lua.state, index) != 0; } /// Pushes the length of the value at the given index onto the stack /// Equivalent to the # operator in Lua - /// See https://www.lua.org/manual/5.4/manual.html#lua_len + /// See https://www.lua.org/manual/5.2/manual.html#lua_len pub fn len(lua: *Lua, index: i32) void { c.lua_len(lua.state, index); } /// Loads a Lua chunk without running it /// If there are no errors, pushes the compiled chunk on the top of the stack as a function - /// See https://www.lua.org/manual/5.4/manual.html#lua_load + /// See https://www.lua.org/manual/5.2/manual.html#lua_load pub fn load(lua: *Lua, reader: CReaderFn, data: *anyopaque, chunk_name: [:0]const u8, mode: Mode) !void { const mode_str = switch (mode) { .binary => "b", @@ -678,7 +689,7 @@ pub const Lua = struct { } /// Creates a new independent state and returns its main thread - /// See https://www.lua.org/manual/5.4/manual.html#lua_newstate + /// See https://www.lua.org/manual/5.2/manual.html#lua_newstate pub fn newState(alloc_fn: AllocFn, data: ?*anyopaque) !Lua { const state = c.lua_newstate(alloc_fn, data) orelse return error.Memory; return Lua{ .state = state }; @@ -686,23 +697,21 @@ pub const Lua = struct { /// Creates a new empty table and pushes it onto the stack /// Equivalent to createTable(0, 0) - /// See https://www.lua.org/manual/5.4/manual.html#lua_newtable + /// See https://www.lua.org/manual/5.2/manual.html#lua_newtable pub fn newTable(lua: *Lua) void { c.lua_newtable(lua.state); } /// Creates a new thread, pushes it on the stack, and returns a Lua state that represents the new thread /// The new thread shares the global environment but has a separate execution stack - /// See https://www.lua.org/manual/5.4/manual.html#lua_newthread + /// See https://www.lua.org/manual/5.2/manual.html#lua_newthread pub fn newThread(lua: *Lua) Lua { const state = c.lua_newthread(lua.state).?; return .{ .state = state }; } - /// This function allocates a new block of memory with the given size, - /// pushes onto the stack a new full userdata with the block address, - /// and returns this address. The host program can freely use this memory - /// See https://www.lua.org/manual/5.3/manual.html#lua_newuserdata + /// This function allocates a new userdata of the given type + /// See https://www.lua.org/manual/5.2/manual.html#lua_newuserdata pub fn newUserdata(lua: *Lua, comptime T: type) *T { // safe to .? because this function throws a Lua error on out of memory // so the returned pointer should never be null @@ -711,15 +720,15 @@ pub const Lua = struct { } /// Pops a key from the stack, and pushes a key-value pair from the table at the given index - /// See https://www.lua.org/manual/5.4/manual.html#lua_next + /// See https://www.lua.org/manual/5.2/manual.html#lua_next pub fn next(lua: *Lua, index: i32) bool { return c.lua_next(lua.state, index) != 0; } /// Calls a function (or callable object) in protected mode + /// See https://www.lua.org/manual/5.2/manual.html#lua_pcall pub fn protectedCall(lua: *Lua, num_args: i32, num_results: i32, msg_handler: i32) !void { // The translate-c version of lua_pcall does not type-check so we must rewrite it - // (macros don't always translate well with translate-c) const ret = c.lua_pcallk(lua.state, num_args, num_results, msg_handler, 0, null); switch (ret) { StatusCode.ok => return, @@ -732,6 +741,7 @@ pub const Lua = struct { } /// Behaves exactly like `Lua.protectedCall()` except that it allows the called function to yield + /// See https://www.lua.org/manual/5.2/manual.html#lua_pcallk pub fn protectedCallCont(lua: *Lua, num_args: i32, num_results: i32, msg_handler: i32, ctx: i32, k: CFn) !void { const ret = c.lua_pcallk(lua.state, num_args, num_results, msg_handler, ctx, k); switch (ret) { @@ -745,33 +755,39 @@ pub const Lua = struct { } /// Pops `n` elements from the top of the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_pop pub fn pop(lua: *Lua, n: i32) void { lua.setTop(-n - 1); } /// Pushes a boolean value with value `b` onto the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushboolean pub fn pushBoolean(lua: *Lua, b: bool) void { c.lua_pushboolean(lua.state, @boolToInt(b)); } /// Pushes a new Closure onto the stack /// `n` tells how many upvalues this function will have + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushcclosure pub fn pushClosure(lua: *Lua, c_fn: CFn, n: i32) void { c.lua_pushcclosure(lua.state, c_fn, n); } /// Pushes a function onto the stack. /// Equivalent to pushClosure with no upvalues + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushcfunction pub fn pushFunction(lua: *Lua, c_fn: CFn) void { lua.pushClosure(c_fn, 0); } /// Push a formatted string onto the stack and return a pointer to the string + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushfstring pub fn pushFString(lua: *Lua, fmt: [:0]const u8, args: anytype) [*:0]const u8 { return @call(.auto, c.lua_pushfstring, .{ lua.state, fmt.ptr } ++ args); } /// Pushes the global environment onto the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushglobaltable pub fn pushGlobalTable(lua: *Lua) void { // lua_pushglobaltable is a macro and c-translate assumes it returns opaque // so just reimplement the macro here @@ -780,26 +796,31 @@ pub const Lua = struct { } /// Pushes an integer with value `n` onto the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushinteger pub fn pushInteger(lua: *Lua, n: Integer) void { c.lua_pushinteger(lua.state, n); } /// Pushes a light userdata onto the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_lightuserdata pub fn pushLightUserdata(lua: *Lua, ptr: *anyopaque) void { c.lua_pushlightuserdata(lua.state, ptr); } /// Pushes the bytes onto the stack. Returns a slice pointing to Lua's internal copy of the string + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushlstring pub fn pushBytes(lua: *Lua, bytes: []const u8) []const u8 { return c.lua_pushlstring(lua.state, bytes.ptr, bytes.len)[0..bytes.len]; } /// Pushes a nil value onto the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushnil pub fn pushNil(lua: *Lua) void { c.lua_pushnil(lua.state); } /// Pushes a float with value `n` onto the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushnumber pub fn pushNumber(lua: *Lua, n: Number) void { c.lua_pushnumber(lua.state, n); } @@ -807,22 +828,26 @@ pub const Lua = struct { /// Pushes a zero-terminated string onto the stack /// Lua makes a copy of the string so `str` may be freed immediately after return /// Returns a pointer to the internal Lua string + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushstring pub fn pushString(lua: *Lua, str: [:0]const u8) [:0]const u8 { return c.lua_pushstring(lua.state, str.ptr)[0..str.len :0]; } /// Pushes this thread onto the stack /// Returns true if this thread is the main thread of its state + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushthread pub fn pushThread(lua: *Lua) bool { return c.lua_pushthread(lua.state) != 0; } /// Pushes a number with value n onto the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushunsigned pub fn pushUnsigned(lua: *Lua, n: Unsigned) void { return c.lua_pushunsigned(lua.state, n); } /// Pushes a copy of the element at the given index onto the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_pushvalue pub fn pushValue(lua: *Lua, index: i32) void { c.lua_pushvalue(lua.state, index); } @@ -830,23 +855,27 @@ pub const Lua = struct { /// Returns true if the two values in indices `index1` and `index2` are primitively equal /// Bypasses __eq metamethods /// Returns false if not equal, or if any index is invalid + /// See https://www.lua.org/manual/5.2/manual.html#lua_rawequal pub fn rawEqual(lua: *Lua, index1: i32, index2: i32) bool { return c.lua_rawequal(lua.state, index1, index2) != 0; } /// Similar to `Lua.getTable()` but does a raw access (without metamethods) + /// See https://www.lua.org/manual/5.2/manual.html#lua_rawget pub fn rawGetTable(lua: *Lua, index: i32) void { c.lua_rawget(lua.state, index); } /// Pushes onto the stack the value t[n], where `t` is the table at the given `index` /// Returns the `LuaType` of the pushed value + /// See https://www.lua.org/manual/5.2/manual.html#lua_rawgeti pub fn rawGetIndex(lua: *Lua, index: i32, n: i32) void { c.lua_rawgeti(lua.state, index, n); } /// Pushes onto the stack the value t[k] where t is the table at the given `index` and /// k is the pointer `p` represented as a light userdata + /// See https://www.lua.org/manual/5.2/manual.html#lua_rawgetp pub fn rawGetPtr(lua: *Lua, index: i32, p: *const anyopaque) void { c.lua_rawgetp(lua.state, index, p); } @@ -855,11 +884,13 @@ pub const Lua = struct { /// For strings it is the length; for tables it is the result of the `#` operator /// For userdata it is the size of the block of memory /// For other values the call returns 0 + /// See https://www.lua.org/manual/5.2/manual.html#lua_rawlen pub fn rawLen(lua: *Lua, index: i32) usize { return c.lua_rawlen(lua.state, index); } /// Similar to `Lua.setTable()` but does a raw assignment (without metamethods) + /// See https://www.lua.org/manual/5.2/manual.html#lua_rawset pub fn rawSetTable(lua: *Lua, index: i32) void { c.lua_rawset(lua.state, index); } @@ -867,6 +898,7 @@ pub const Lua = struct { /// Does the equivalent of t[`i`] = v where t is the table at the given `index` /// and v is the value at the top of the stack /// Pops the value from the stack. Does not use __newindex metavalue + /// See https://www.lua.org/manual/5.2/manual.html#lua_rawseti pub fn rawSetIndex(lua: *Lua, index: i32, i: i32) void { c.lua_rawseti(lua.state, index, i); } @@ -874,22 +906,26 @@ pub const Lua = struct { /// Does the equivalent of t[p] = v where t is the table at the given `index` /// `p` is encoded as a light user data, and v is the value at the top of the stack /// Pops the value from the stack. Does not use __newindex metavalue + /// See https://www.lua.org/manual/5.2/manual.html#lua_rawsetp pub fn rawSetPtr(lua: *Lua, index: i32, p: *const anyopaque) void { c.lua_rawsetp(lua.state, index, p); } /// Sets the C function f as the new value of global name + /// See https://www.lua.org/manual/5.2/manual.html#lua_register pub fn register(lua: *Lua, name: [:0]const u8, c_fn: CFn) void { c.lua_register(lua.state, name.ptr, c_fn); } /// Removes the element at the given valid `index` shifting down elements to fill the gap + /// See https://www.lua.org/manual/5.2/manual.html#lua_remove pub fn remove(lua: *Lua, index: i32) void { c.lua_remove(lua.state, index); } /// Moves the top element into the given valid `index` without shifting any elements, /// then pops the top element + /// See https://www.lua.org/manual/5.2/manual.html#lua_replace pub fn replace(lua: *Lua, index: i32) void { // translate-c cannot translate this macro correctly // c.lua_replace(lua.state, index); @@ -898,6 +934,7 @@ pub const Lua = struct { } /// Starts and resumes a coroutine in the given thread + /// See https://www.lua.org/manual/5.2/manual.html#lua_resume pub fn resumeThread(lua: *Lua, from: ?Lua, num_args: i32) !ResumeStatus { const from_state = if (from) |from_val| from_val.state else null; const thread_status = c.lua_resume(lua.state, from_state, num_args); @@ -911,30 +948,33 @@ pub const Lua = struct { } /// Changes the allocator function of a given state to `alloc_fn` with userdata `data` + /// See https://www.lua.org/manual/5.2/manual.html#lua_setallocf pub fn setAllocF(lua: *Lua, alloc_fn: AllocFn, data: ?*anyopaque) void { c.lua_setallocf(lua.state, alloc_fn, data); } /// Does the equivalent to t[`k`] = v where t is the value at the given `index` /// and v is the value on the top of the stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_setfield pub fn setField(lua: *Lua, index: i32, k: [:0]const u8) void { c.lua_setfield(lua.state, index, k.ptr); } /// Pops a value from the stack and sets it as the new value of global `name` + /// See https://www.lua.org/manual/5.2/manual.html#lua_setglobal pub fn setGlobal(lua: *Lua, name: [:0]const u8) void { c.lua_setglobal(lua.state, name.ptr); } - /// Pops a value from the stack and sets it as the user value associated to - /// the full userdata at the given index + /// Pops a value from the stack and sets it as the user value associated to the full userdata at the given index /// Returns an error if the userdata does not have that value + /// See https://www.lua.org/manual/5.2/manual.html#lua_setuservalue pub fn setUserValue(lua: *Lua, index: i32) !void { c.lua_setuservalue(lua.state, index); } - /// Pops a table or nil from the stack and sets that value as the new metatable for the - /// value at the given `index` + /// Pops a table or nil from the stack and sets that value as the new metatable for the value at the given `index` + /// See https://www.lua.org/manual/5.2/manual.html#lua_setmetatable pub fn setMetatable(lua: *Lua, index: i32) void { // lua_setmetatable always returns 1 so is safe to ignore _ = c.lua_setmetatable(lua.state, index); @@ -942,6 +982,7 @@ pub const Lua = struct { /// Does the equivalent to t[k] = v, where t is the value at the given `index` /// v is the value on the top of the stack, and k is the value just below the top + /// See https://www.lua.org/manual/5.2/manual.html#lua_settable pub fn setTable(lua: *Lua, index: i32) void { c.lua_settable(lua.state, index); } @@ -949,23 +990,27 @@ pub const Lua = struct { /// Sets the top of the stack to `index` /// If the new top is greater than the old, new elements are filled with nil /// If `index` is 0 all stack elements are removed + /// See https://www.lua.org/manual/5.2/manual.html#lua_settop pub fn setTop(lua: *Lua, index: i32) void { c.lua_settop(lua.state, index); } /// Returns the status of this thread + /// See https://www.lua.org/manual/5.2/manual.html#lua_status pub fn status(lua: *Lua) Status { return @intToEnum(Status, c.lua_status(lua.state)); } /// Converts the Lua value at the given `index` into a boolean /// The Lua value at the index will be considered true unless it is false or nil + /// See https://www.lua.org/manual/5.2/manual.html#lua_toboolean pub fn toBoolean(lua: *Lua, index: i32) bool { return c.lua_toboolean(lua.state, index) != 0; } /// Converts a value at the given `index` into a CFn /// Returns an error if the value is not a CFn + /// See https://www.lua.org/manual/5.2/manual.html#lua_tocfunction pub fn toCFunction(lua: *Lua, index: i32) !CFn { return c.lua_tocfunction(lua.state, index) orelse return error.Fail; } @@ -973,6 +1018,7 @@ pub const Lua = struct { /// Converts the Lua value at the given `index` to a signed integer /// The Lua value must be an integer, or a number, or a string convertible to an integer otherwise toIntegerX returns 0 /// Returns an error if the conversion failed + /// See https://www.lua.org/manual/5.2/manual.html#lua_tointegerx pub fn toInteger(lua: *Lua, index: i32) !Integer { var success: c_int = undefined; const result = c.lua_tointegerx(lua.state, index, &success); @@ -983,6 +1029,7 @@ pub const Lua = struct { /// Returns a slice of bytes at the given index /// If the value is not a string or number, returns an error /// If the value was a number the actual value in the stack will be changed to a string + /// See https://www.lua.org/manual/5.2/manual.html#lua_tolstring pub fn toBytes(lua: *Lua, index: i32) ![:0]const u8 { var length: usize = undefined; if (c.lua_tolstring(lua.state, index, &length)) |ptr| return ptr[0..length :0]; @@ -992,6 +1039,7 @@ pub const Lua = struct { /// Converts the Lua value at the given `index` to a float /// The Lua value must be a number or a string convertible to a number otherwise toNumberX returns 0 /// Returns an error if the conversion failed + /// See https://www.lua.org/manual/5.2/manual.html#lua_tonumberx pub fn toNumber(lua: *Lua, index: i32) !Number { var success: c_int = undefined; const result = c.lua_tonumberx(lua.state, index, &success); @@ -1000,6 +1048,7 @@ pub const Lua = struct { } /// Converts the value at the given `index` to an opaque pointer + /// See https://www.lua.org/manual/5.2/manual.html#lua_topointer pub fn toPointer(lua: *Lua, index: i32) !*const anyopaque { if (c.lua_topointer(lua.state, index)) |ptr| return ptr; return error.Fail; @@ -1008,6 +1057,7 @@ pub const Lua = struct { /// Converts the Lua value at the given `index` to a zero-terminated many-itemed-pointer (string) /// Returns an error if the conversion failed /// If the value was a number the actual value in the stack will be changed to a string + /// See https://www.lua.org/manual/5.2/manual.html#lua_tostring pub fn toString(lua: *Lua, index: i32) ![*:0]const u8 { var length: usize = undefined; if (c.lua_tolstring(lua.state, index, &length)) |str| return str; @@ -1017,6 +1067,7 @@ pub const Lua = struct { /// Converts the value at the given `index` to a Lua thread (wrapped with a `Lua` struct) /// The thread does _not_ contain an allocator because it is not the main thread and should therefore not be used with `deinit()` /// Returns an error if the value is not a thread + /// See https://www.lua.org/manual/5.2/manual.html#lua_tothread pub fn toThread(lua: *Lua, index: i32) !Lua { const thread = c.lua_tothread(lua.state, index); if (thread) |thread_ptr| return Lua{ .state = thread_ptr }; @@ -1025,6 +1076,7 @@ pub const Lua = struct { /// Converts the Lua value at the given index to an unsigned integer /// The Lua value must be a number or a string convertible to a number otherwise an error is returned + /// See https://www.lua.org/manual/5.2/manual.html#lua_tounsignedx pub fn toUnsigned(lua: *Lua, index: i32) !Unsigned { var success: c_int = undefined; const result = c.lua_tounsignedx(lua.state, index, &success); @@ -1034,6 +1086,7 @@ pub const Lua = struct { /// Returns a pointer of the given type to the userdata at the given index. /// Works for both full and light userdata. Otherwise returns an error. + /// See https://www.lua.org/manual/5.2/manual.html#lua_touserdata pub fn toUserdata(lua: *Lua, comptime T: type, index: i32) !*T { if (c.lua_touserdata(lua.state, index)) |ptr| return opaqueCast(T, ptr); return error.Fail; @@ -1041,33 +1094,40 @@ pub const Lua = struct { /// Returns the `LuaType` of the value at the given index /// Note that this is equivalent to lua_type but because type is a Zig primitive it is renamed to `typeOf` + /// See https://www.lua.org/manual/5.2/manual.html#lua_type pub fn typeOf(lua: *Lua, index: i32) LuaType { return @intToEnum(LuaType, c.lua_type(lua.state, index)); } /// Returns the name of the given `LuaType` as a null-terminated slice + /// See https://www.lua.org/manual/5.2/manual.html#lua_typename pub fn typeName(lua: *Lua, t: LuaType) [:0]const u8 { return std.mem.span(c.lua_typename(lua.state, @enumToInt(t))); } /// Returns the pseudo-index that represents the `i`th upvalue of the running function + /// See https://www.lua.org/manual/5.2/manual.html#lua_upvalueindex pub fn upvalueIndex(i: i32) i32 { return c.lua_upvalueindex(i); } /// Returns the version number of this core - /// TODO: should we just deref? - pub fn version(lua: *Lua) *const Number { + /// When `caller_version` is true it returns the address of the version running the call + /// See https://www.lua.org/manual/5.2/manual.html#lua_version + pub fn version(lua: *Lua, caller_version: bool) *const Number { + if (caller_version) return c.lua_version(null); return c.lua_version(lua.state); } /// Pops `num` values from the current stack and pushes onto the stack of `to` + /// See https://www.lua.org/manual/5.2/manual.html#lua_xmove pub fn xMove(lua: *Lua, to: Lua, num: i32) void { c.lua_xmove(lua.state, to.state, num); } /// This function is equivalent to `Lua.yieldCont()` but has no continuation /// NOTE: look into the lua_yieldk docs about this and debug hooks and noreturn + /// See https://www.lua.org/manual/5.2/manual.html#lua_yield pub fn yield(lua: *Lua, num_results: i32) noreturn { // translate-c failed to pass NULL correctly _ = c.lua_yieldk(lua.state, num_results, 0, null); @@ -1075,6 +1135,7 @@ pub const Lua = struct { } /// Yields this coroutine (thread) + /// See https://www.lua.org/manual/5.2/manual.html#lua_yieldk pub fn yieldCont(lua: *Lua, num_results: i32, ctx: i32, k: CFn) noreturn { _ = c.lua_yieldk(lua.state, num_results, ctx, k); unreachable; @@ -1086,16 +1147,19 @@ pub const Lua = struct { // Each is kept similar to the original C API function while also making it easy to use from Zig /// Returns the current hook function + /// See https://www.lua.org/manual/5.2/manual.html#lua_gethook pub fn getHook(lua: *Lua) ?CHookFn { return c.lua_gethook(lua.state); } /// Returns the current hook count + /// See https://www.lua.org/manual/5.2/manual.html#lua_gethookcount pub fn getHookCount(lua: *Lua) i32 { return c.lua_gethookcount(lua.state); } /// Returns the current hook mask + /// See https://www.lua.org/manual/5.2/manual.html#lua_gethookmask pub fn getHookMask(lua: *Lua) HookMask { return HookMask.fromInt(c.lua_gethookmask(lua.state)); } @@ -1103,6 +1167,7 @@ pub const Lua = struct { /// Gets information about a specific function or function invocation /// Returns an error if an invalid option was given, but the valid options /// are still handled + /// See https://www.lua.org/manual/5.2/manual.html#lua_getinfo pub fn getInfo(lua: *Lua, options: DebugInfo.Options, info: *DebugInfo) void { const str = options.toString(); @@ -1151,6 +1216,7 @@ pub const Lua = struct { /// Gets information about a local variable /// Returns the name of the local variable + /// See https://www.lua.org/manual/5.2/manual.html#lua_getlocal pub fn getLocal(lua: *Lua, info: *DebugInfo, n: i32) ![:0]const u8 { var ar: Debug = undefined; ar.i_ci = @ptrCast(*c.struct_CallInfo, info.private); @@ -1161,6 +1227,7 @@ pub const Lua = struct { } /// Gets information about the interpreter runtime stack + /// See https://www.lua.org/manual/5.2/manual.html#lua_getstack pub fn getStack(lua: *Lua, level: i32) !DebugInfo { var ar: Debug = undefined; if (c.lua_getstack(lua.state, level, &ar) == 0) return error.Fail; @@ -1168,6 +1235,7 @@ pub const Lua = struct { } /// Gets information about the `n`th upvalue of the closure at index `func_index` + /// See https://www.lua.org/manual/5.2/manual.html#lua_getupvalue pub fn getUpvalue(lua: *Lua, func_index: i32, n: i32) ![:0]const u8 { if (c.lua_getupvalue(lua.state, func_index, n)) |name| { return std.mem.span(name); @@ -1176,6 +1244,7 @@ pub const Lua = struct { } /// Sets the debugging hook function + /// See https://www.lua.org/manual/5.2/manual.html#lua_sethook pub fn setHook(lua: *Lua, hook_fn: CHookFn, mask: HookMask, count: i32) void { const hook_mask = HookMask.toInt(mask); _ = c.lua_sethook(lua.state, hook_fn, hook_mask, count); @@ -1184,6 +1253,7 @@ pub const Lua = struct { /// Sets the value of a local variable /// Returns an error when the index is greater than the number of active locals /// Returns the name of the local variable + /// See https://www.lua.org/manual/5.2/manual.html#lua_setlocal pub fn setLocal(lua: *Lua, info: *DebugInfo, n: i32) ![:0]const u8 { var ar: Debug = undefined; ar.i_ci = @ptrCast(*c.struct_CallInfo, info.private); @@ -1195,6 +1265,7 @@ pub const Lua = struct { /// Sets the value of a closure's upvalue /// Returns the name of the upvalue or an error if the upvalue does not exist + /// See https://www.lua.org/manual/5.2/manual.html#lua_setupvalue pub fn setUpvalue(lua: *Lua, func_index: i32, n: i32) ![:0]const u8 { if (c.lua_setupvalue(lua.state, func_index, n)) |name| { return std.mem.span(name); @@ -1203,6 +1274,7 @@ pub const Lua = struct { } /// Returns a unique identifier for the upvalue numbered `n` from the closure index `func_index` + /// See https://www.lua.org/manual/5.2/manual.html#lua_upvalueid pub fn upvalueId(lua: *Lua, func_index: i32, n: i32) !*anyopaque { if (c.lua_upvalueid(lua.state, func_index, n)) |ptr| return ptr; return error.Fail; @@ -1210,6 +1282,7 @@ pub const Lua = struct { /// Make the `n1`th upvalue of the Lua closure at index `func_index1` refer to the `n2`th upvalue /// of the Lua closure at index `func_index2` + /// See https://www.lua.org/manual/5.2/manual.html#lua_upvaluejoin pub fn upvalueJoin(lua: *Lua, func_index1: i32, n1: i32, func_index2: i32, n2: i32) void { c.lua_upvaluejoin(lua.state, func_index1, n1, func_index2, n2); } @@ -1221,33 +1294,45 @@ pub const Lua = struct { /// Checks whether `cond` is true. Raises an error using `Lua.argError()` if not /// Possibly never returns + /// See https://www.lua.org/manual/5.2/manual.html#lua_argcheck pub fn argCheck(lua: *Lua, cond: bool, arg: i32, extra_msg: [:0]const u8) void { // translate-c failed if (cond) lua.argError(arg, extra_msg); } /// Raises an error reporting a problem with argument `arg` of the C function that called it + /// See https://www.lua.org/manual/5.2/manual.html#luaL_argerror pub fn argError(lua: *Lua, arg: i32, extra_msg: [*:0]const u8) noreturn { _ = c.luaL_argerror(lua.state, arg, extra_msg); unreachable; } /// Calls a metamethod + /// See https://www.lua.org/manual/5.2/manual.html#luaL_callmeta pub fn callMeta(lua: *Lua, obj: i32, field: [:0]const u8) !void { if (c.luaL_callmeta(lua.state, obj, field.ptr) == 0) return error.Fail; } /// Checks whether the function has an argument of any type at position `arg` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkany pub fn checkAny(lua: *Lua, arg: i32) void { c.luaL_checkany(lua.state, arg); } + /// Checks whether the function argument `arg` is a number and returns this number cast to an i32 + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkint + pub fn checkInt(lua: *Lua, arg: i32) i32 { + return c.luaL_checkint(lua.state, arg); + } + /// Checks whether the function argument `arg` is an integer (or can be converted to an integer) and returns the integer + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkinteger pub fn checkInteger(lua: *Lua, arg: i32) Integer { return c.luaL_checkinteger(lua.state, arg); } /// Checks whether the function argument `arg` is a slice of bytes and returns the slice + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checklstring pub fn checkBytes(lua: *Lua, arg: i32) [:0]const u8 { var length: usize = 0; const str = c.luaL_checklstring(lua.state, arg, &length); @@ -1256,6 +1341,7 @@ pub const Lua = struct { } /// Checks whether the function argument `arg` is a number and returns the number + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checknumber pub fn checkNumber(lua: *Lua, arg: i32) Number { return c.luaL_checknumber(lua.state, arg); } @@ -1264,6 +1350,7 @@ pub const Lua = struct { /// `default` is used as a default value when not null /// Returns the enum value found /// Useful for mapping Lua strings to Zig enums + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkoption pub fn checkOption(lua: *Lua, comptime T: type, arg: i32, default: ?T) T { const name = blk: { if (default) |defaultName| { @@ -1284,40 +1371,47 @@ pub const Lua = struct { /// Grows the stack size to top + `size` elements, raising an error if the stack cannot grow to that size /// `msg` is an additional text to go into the error message + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkstack pub fn checkStackErr(lua: *Lua, size: i32, msg: ?[*:0]const u8) void { c.luaL_checkstack(lua.state, size, msg); } /// Checks whether the function argument `arg` is a string and returns the string /// TODO: check about lua_tolstring for returning the size + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkstring pub fn checkString(lua: *Lua, arg: i32) [*:0]const u8 { return c.luaL_checklstring(lua.state, arg, null); } /// Checks whether the function argument `arg` has type `t` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checktype pub fn checkType(lua: *Lua, arg: i32, t: LuaType) void { c.luaL_checktype(lua.state, arg, @enumToInt(t)); } /// Checks whether the function argument `arg` is a userdata of the type `type_name` /// Returns the userdata's memory-block address + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkudata pub fn checkUserdata(lua: *Lua, comptime T: type, arg: i32) *T { // the returned pointer will not be null return opaqueCast(T, c.luaL_checkudata(lua.state, arg, @typeName(T)).?); } /// Checks whether the function argument arg is a number and returns this number cast to an unsigned + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkunsigned pub fn checkUnsigned(lua: *Lua, arg: i32) Unsigned { return c.luaL_checkunsigned(lua.state, arg); } /// Checks whether the code making the call and the Lua library being called are using /// the same version of Lua and the same numeric types. + /// See https://www.lua.org/manual/5.2/manual.html#luaL_checkversion pub fn checkVersion(lua: *Lua) void { return c.luaL_checkversion_(lua.state, c.LUA_VERSION_NUM); } /// Loads and runs the given file + /// See https://www.lua.org/manual/5.2/manual.html#luaL_dofile pub fn doFile(lua: *Lua, file_name: [:0]const u8) !void { // translate-c failure try lua.loadFile(file_name); @@ -1325,6 +1419,7 @@ pub const Lua = struct { } /// Loads and runs the given string + /// See https://www.lua.org/manual/5.2/manual.html#luaL_dostring pub fn doString(lua: *Lua, str: [:0]const u8) !void { // trnaslate-c failure try lua.loadString(str); @@ -1332,17 +1427,20 @@ pub const Lua = struct { } /// Raises an error + /// See https://www.lua.org/manual/5.2/manual.html#luaL_error pub fn raiseErrorStr(lua: *Lua, fmt: [:0]const u8, args: anytype) noreturn { _ = @call(.auto, c.luaL_error, .{ lua.state, fmt.ptr } ++ args); unreachable; } /// This function produces the return values for process-related functions in the standard library + /// See https://www.lua.org/manual/5.2/manual.html#luaL_execresult pub fn execResult(lua: *Lua, stat: i32) i32 { return c.luaL_execresult(lua.state, stat); } /// This function produces the return values for file-related functions in the standard library + /// See https://www.lua.org/manual/5.2/manual.html#luaL_fileresult pub fn fileResult(lua: *Lua, stat: i32, file_name: [:0]const u8) i32 { return c.luaL_fileresult(lua.state, stat, file_name.ptr); } @@ -1350,6 +1448,7 @@ pub const Lua = struct { /// Pushes onto the stack the field `e` from the metatable of the object at index `obj` /// and returns the type of the pushed value /// TODO: possibly return an error if nil + /// See https://www.lua.org/manual/5.2/manual.html#luaL_getmetafield pub fn getMetaField(lua: *Lua, obj: i32, field: [:0]const u8) !LuaType { const val_type = @intToEnum(LuaType, c.luaL_getmetafield(lua.state, obj, field.ptr)); if (val_type == .nil) return error.Fail; @@ -1359,33 +1458,39 @@ pub const Lua = struct { /// Pushes onto the stack the metatable associated with the name `type_name` in the registry /// or nil if there is no metatable associated with that name. Returns the type of the pushed value /// TODO: return error when type is nil? + /// See https://www.lua.org/manual/5.2/manual.html#luaL_getmetatable pub fn getMetatableRegistry(lua: *Lua, table_name: [:0]const u8) void { c.luaL_getmetatable(lua.state, table_name.ptr); } /// Ensures that the value t[`field`], where t is the value at `index`, is a table, and pushes that table onto the stack. + /// See https://www.lua.org/manual/5.2/manual.html#luaL_getsubtable pub fn getSubtable(lua: *Lua, index: i32, field: [:0]const u8) !void { if (c.luaL_getsubtable(lua.state, index, field.ptr) == 0) return error.Fail; } /// Creates a copy of string `str`, replacing any occurrence of the string `pat` with the string `rep` /// Pushes the resulting string on the stack and returns it. + /// See https://www.lua.org/manual/5.2/manual.html#luaL_gsub pub fn globalSub(lua: *Lua, str: [:0]const u8, pat: [:0]const u8, rep: [:0]const u8) [:0]const u8 { return std.mem.span(c.luaL_gsub(lua.state, str.ptr, pat.ptr, rep.ptr)); } /// Returns the "length" of the value at the given index as a number /// it is equivalent to the '#' operator in Lua + /// See https://www.lua.org/manual/5.2/manual.html#luaL_len pub fn lenRaiseErr(lua: *Lua, index: i32) i64 { return c.luaL_len(lua.state, index); } /// The same as `Lua.loadBufferX` with `mode` set to binary+text + /// See https://www.lua.org/manual/5.2/manual.html#luaL_loadbuffer pub fn loadBuffer(lua: *Lua, buf: []const u8, name: [:0]const u8) !void { try lua.loadBufferX(buf, name, .binary_text); } /// Loads a buffer as a Lua chunk + /// See https://www.lua.org/manual/5.2/manual.html#luaL_loadbufferx pub fn loadBufferX(lua: *Lua, buf: []const u8, name: [:0]const u8, mode: Mode) !void { const mode_str = switch (mode) { .binary => "b", @@ -1401,11 +1506,13 @@ pub const Lua = struct { } /// Equivalent to `Lua.loadFileX()` with mode equal to binary+text + /// See https://www.lua.org/manual/5.2/manual.html#luaL_loadfile pub fn loadFile(lua: *Lua, file_name: [:0]const u8) !void { try lua.loadFileX(file_name, .binary_text); } /// Loads a file as a Lua chunk + /// See https://www.lua.org/manual/5.2/manual.html#luaL_loadfilex pub fn loadFileX(lua: *Lua, file_name: [:0]const u8, mode: Mode) !void { const mode_str = switch (mode) { .binary => "b", @@ -1424,6 +1531,7 @@ pub const Lua = struct { } /// Loads a string as a Lua chunk + /// See https://www.lua.org/manual/5.2/manual.html#luaL_loadstring pub fn loadString(lua: *Lua, str: [:0]const u8) !void { const ret = c.luaL_loadstring(lua.state, str.ptr); switch (ret) { @@ -1438,6 +1546,7 @@ pub const Lua = struct { } /// Creates a new table and registers there the functions in `list` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_newlib pub fn newLib(lua: *Lua, list: []const FnReg) void { // translate-c failure lua.checkVersion(); @@ -1446,6 +1555,7 @@ pub const Lua = struct { } /// Creates a new table with a size optimized to store all entries in the array `list` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_newlibtable pub fn newLibTable(lua: *Lua, list: []const FnReg) void { // translate-c failure lua.createTable(0, @intCast(i32, list.len)); @@ -1453,11 +1563,13 @@ pub const Lua = struct { /// If the registry already has the key `key`, returns an error /// Otherwise, creates a new table to be used as a metatable for userdata + /// See https://www.lua.org/manual/5.2/manual.html#luaL_newmetatable pub fn newMetatable(lua: *Lua, key: [:0]const u8) !void { if (c.luaL_newmetatable(lua.state, key.ptr) == 0) return error.Fail; } /// Creates a new Lua state with an allocator using the default libc allocator + /// See https://www.lua.org/manual/5.2/manual.html#luaL_newstate pub fn newStateLibc() !Lua { const state = c.luaL_newstate() orelse return error.Memory; return Lua{ .state = state }; @@ -1465,14 +1577,23 @@ pub const Lua = struct { // luaL_opt (a macro) really isn't that useful, so not going to implement for now + /// If the function argument `arg` is a number, returns this number cast to an i32. + /// If the argument is absent or nil returns `default` + /// /// See https://www.lua.org/manual/5.2/manual.html#luaL_optint + pub fn optInt(lua: *Lua, arg: i32, default: i32) i32 { + return c.luaL_optint(lua.state, arg, default); + } + /// If the function argument `arg` is an integer, returns the integer /// If the argument is absent or nil returns `default` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_optinteger pub fn optInteger(lua: *Lua, arg: i32, default: Integer) Integer { return c.luaL_optinteger(lua.state, arg, default); } /// If the function argument `arg` is a slice of bytes, returns the slice /// If the argument is absent or nil returns `default` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_optlstring pub fn optBytes(lua: *Lua, arg: i32, default: [:0]const u8) [:0]const u8 { var length: usize = 0; // will never return null because default cannot be null @@ -1483,12 +1604,14 @@ pub const Lua = struct { /// If the function argument `arg` is a number, returns the number /// If the argument is absent or nil returns `default` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_optnumber pub fn optNumber(lua: *Lua, arg: i32, default: Number) Number { return c.luaL_optnumber(lua.state, arg, default); } /// If the function argument `arg` is a string, returns the string /// If the argment is absent or nil returns `default` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_optlstring pub fn optString(lua: *Lua, arg: i32, default: [:0]const u8) [*:0]const u8 { // translate-c error return c.luaL_optlstring(lua.state, arg, default.ptr, null); @@ -1496,12 +1619,14 @@ pub const Lua = struct { /// If the function argument is a number, returns this number as an unsigned /// If the argument is absent or nil returns default, otherwise raises an error + /// See https://www.lua.org/manual/5.2/manual.html#luaL_optunsigned pub fn optUnsigned(lua: *Lua, arg: i32, default: Unsigned) Unsigned { return c.luaL_optunsigned(lua.state, arg, default); } /// Creates and returns a reference in the table at index `index` for the object on the top of the stack /// Pops the object + /// See https://www.lua.org/manual/5.2/manual.html#luaL_ref pub fn ref(lua: *Lua, index: i32) !i32 { const ret = c.luaL_ref(lua.state, index); return if (ret == ref_nil) error.Fail else ret; @@ -1509,12 +1634,14 @@ pub const Lua = struct { /// If package.loaded[`mod_name`] is not true, calls the function `open_fn` with `mod_name` /// as an argument and sets the call result to package.loaded[`mod_name`] + /// See https://www.lua.org/manual/5.2/manual.html#luaL_requiref pub fn requireF(lua: *Lua, mod_name: [:0]const u8, open_fn: CFn, global: bool) void { c.luaL_requiref(lua.state, mod_name.ptr, open_fn, @boolToInt(global)); } /// Registers all functions in the array `fns` into the table on the top of the stack /// All functions are created with `num_upvalues` upvalues + /// See https://www.lua.org/manual/5.2/manual.html#luaL_setfuncs pub fn setFuncs(lua: *Lua, funcs: []const FnReg, num_upvalues: i32) void { lua.checkStackErr(num_upvalues, "too many upvalues"); for (funcs) |f| { @@ -1531,11 +1658,13 @@ pub const Lua = struct { /// Sets the metatable of the object on the top of the stack as the metatable associated /// with `table_name` in the registry + /// See https://www.lua.org/manual/5.2/manual.html#luaL_setmetatable pub fn setMetatableRegistry(lua: *Lua, table_name: [:0]const u8) void { c.luaL_setmetatable(lua.state, table_name.ptr); } /// This function works like `Lua.checkUserdata()` except it returns a Zig error instead of raising a Lua error on fail + /// See https://www.lua.org/manual/5.2/manual.html#luaL_testudata pub fn testUserdata(lua: *Lua, comptime T: type, arg: i32) !*T { if (c.luaL_testudata(lua.state, arg, @typeName(T))) |ptr| { return opaqueCast(T, ptr); @@ -1543,6 +1672,7 @@ pub const Lua = struct { } /// Converts any Lua value at the given index into a string in a reasonable format + /// See https://www.lua.org/manual/5.2/manual.html#luaL_tolstring pub fn toBytesFmt(lua: *Lua, index: i32) [:0]const u8 { var length: usize = undefined; const ptr = c.luaL_tolstring(lua.state, index, &length); @@ -1550,21 +1680,25 @@ pub const Lua = struct { } /// Creates and pushes a traceback of the stack of `other` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_traceback pub fn traceback(lua: *Lua, other: *Lua, msg: [:0]const u8, level: i32) void { c.luaL_traceback(lua.state, other.state, msg.ptr, level); } /// Returns the name of the type of the value at the given `index` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_typename pub fn typeNameIndex(lua: *Lua, index: i32) [:0]const u8 { return std.mem.span(c.luaL_typename(lua.state, index)); } /// Releases the reference `r` from the table at index `index` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_unref pub fn unref(lua: *Lua, index: i32, r: i32) void { c.luaL_unref(lua.state, index, r); } /// Pushes onto the stack a string identifying the current position of the control + /// See https://www.lua.org/manual/5.2/manual.html#luaL_where /// at the call stack `level` pub fn where(lua: *Lua, level: i32) void { c.luaL_where(lua.state, level); @@ -1650,11 +1784,13 @@ pub const Buffer = struct { b: LuaBuffer = undefined, /// Initialize a Lua string buffer + /// See https://www.lua.org/manual/5.2/manual.html#luaL_buffinit pub fn init(buf: *Buffer, lua: Lua) void { c.luaL_buffinit(lua.state, &buf.b); } /// Initialize a Lua string buffer with an initial size + /// See https://www.lua.org/manual/5.2/manual.html#luaL_buffinitsize pub fn initSize(buf: *Buffer, lua: Lua, size: usize) []u8 { return c.luaL_buffinitsize(lua.state, &buf.b, size)[0..size]; } @@ -1665,6 +1801,7 @@ pub const Buffer = struct { pub const buffer_size = c.LUAL_BUFFERSIZE; /// Adds `byte` to the buffer + /// See https://www.lua.org/manual/5.2/manual.html#luaL_addchar pub fn addChar(buf: *Buffer, byte: u8) void { // could not be translated by translate-c var lua_buf = &buf.b; @@ -1674,11 +1811,13 @@ pub const Buffer = struct { } /// Adds the string to the buffer + /// See https://www.lua.org/manual/5.2/manual.html#luaL_addlstring pub fn addBytes(buf: *Buffer, str: []const u8) void { c.luaL_addlstring(&buf.b, str.ptr, str.len); } /// Adds to the buffer a string of `length` previously copied to the buffer area + /// See https://www.lua.org/manual/5.2/manual.html#luaL_addsize pub fn addSize(buf: *Buffer, length: usize) void { // another function translate-c couldn't handle // c.luaL_addsize(&buf.b, length); @@ -1687,26 +1826,20 @@ pub const Buffer = struct { } /// Adds the zero-terminated string pointed to by `str` to the buffer + /// See https://www.lua.org/manual/5.2/manual.html#luaL_addstring pub fn addString(buf: *Buffer, str: [:0]const u8) void { c.luaL_addstring(&buf.b, str.ptr); } /// Adds the value on the top of the stack to the buffer /// Pops the value + /// See https://www.lua.org/manual/5.2/manual.html#luaL_addvalue pub fn addValue(buf: *Buffer) void { c.luaL_addvalue(&buf.b); } - /// Removes `num` bytes from the buffer - /// TODO: perhaps error check? - pub fn sub(buf: *Buffer, num: usize) void { - // Another bug with translate-c - // c.luaL_buffsub(&buf.b, num); - var lua_buf = &buf.b; - lua_buf.n -= num; - } - /// Equivalent to prepSize with a buffer size of Buffer.buffer_size + /// See https://www.lua.org/manual/5.2/manual.html#luaL_prepbuffer pub fn prep(buf: *Buffer) []u8 { return buf.prepSize(buffer_size)[0..buffer_size]; } @@ -1714,16 +1847,19 @@ pub const Buffer = struct { /// Returns an address to a space of `size` where you can copy a string /// to be added to the buffer /// you must call `Buffer.addSize` to actually add it to the buffer + /// See https://www.lua.org/manual/5.2/manual.html#luaL_prepbuffsize pub fn prepSize(buf: *Buffer, size: usize) []u8 { return c.luaL_prepbuffsize(&buf.b, size)[0..size]; } /// Finishes the use of the buffer leaving the final string on the top of the stack + /// See https://www.lua.org/manual/5.2/manual.html#luaL_pushresult pub fn pushResult(buf: *Buffer) void { c.luaL_pushresult(&buf.b); } /// Equivalent to `Buffer.addSize()` followed by `Buffer.pushResult()` + /// See https://www.lua.org/manual/5.2/manual.html#luaL_pushresultsize pub fn pushResultSize(buf: *Buffer, size: usize) void { c.luaL_pushresultsize(&buf.b, size); } diff --git a/src/ziglua-5.2/tests.zig b/src/ziglua-5.2/tests.zig index 5acbc60..b5ed46c 100644 --- a/src/ziglua-5.2/tests.zig +++ b/src/ziglua-5.2/tests.zig @@ -403,7 +403,7 @@ test "version" { var lua = try Lua.init(testing.allocator); defer lua.deinit(); - try expectEqual(@as(f64, 502), lua.version().*); + try expectEqual(@as(f64, 502), lua.version(false).*); lua.checkVersion(); } @@ -415,10 +415,7 @@ test "string buffers" { buffer.init(lua); buffer.addChar('z'); - buffer.addChar('i'); - buffer.addChar('g'); - buffer.addString("lua"); - buffer.sub(3); + buffer.addString("ig"); var str = buffer.prepSize(3); str[0] = 'l'; @@ -427,11 +424,10 @@ test "string buffers" { buffer.addSize(3); buffer.addBytes(" api "); - lua.pushNumber(5.4); + lua.pushNumber(5.2); buffer.addValue(); - buffer.sub(4); buffer.pushResult(); - try expectEqualStrings("ziglua api", try lua.toBytes(-1)); + try expectEqualStrings("ziglua api 5.2", try lua.toBytes(-1)); // now test a small buffer buffer = undefined; @@ -561,6 +557,8 @@ test "garbage collector" { _ = lua.gcIsRunning(); _ = lua.gcSetPause(2); _ = lua.gcSetStepMul(2); + lua.gcSetGenerational(); + lua.gcSetGenerational(); } test "table access" { @@ -827,7 +825,7 @@ test "raise error" { } fn continuation(l: *Lua) i32 { - const ctxOrNull = l.getCtx() catch unreachable; + const ctxOrNull = l.getContext() catch unreachable; const ctx = ctxOrNull orelse 0; if (ctx == 5) { _ = l.pushString("done"); @@ -1017,6 +1015,7 @@ test "aux check functions" { const function = ziglua.wrap(struct { fn inner(l: *Lua) i32 { l.checkAny(1); + _ = l.checkInt(2); _ = l.checkInteger(2); _ = l.checkBytes(3); _ = l.checkNumber(4); @@ -1137,6 +1136,7 @@ test "aux opt functions" { const function = ziglua.wrap(struct { fn inner(l: *Lua) i32 { + expectEqual(@as(Integer, 10), l.optInt(1, 10)) catch unreachable; expectEqual(@as(Integer, 10), l.optInteger(1, 10)) catch unreachable; expectEqualStrings("zig", l.optBytes(2, "zig")) catch unreachable; expectEqual(@as(Number, 1.23), l.optNumber(3, 1.23)) catch unreachable;