Skip to content

Commit 55165f4

Browse files
authored
Add support for lua.getStack() (#8)
Added: * Added support for the lua.getStack() function, a function required for inspecting the call stack such as from within error handling functions.
1 parent bf332ec commit 55165f4

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ you.
8787
|-----------------------------|---------------------------------------|
8888
| Lua C API (`lua_*`) | 🎉 100% coverage<sup>†</sup> (92/92) |
8989
| Auxilary Library (`luaL_*`) | 🤩 100% coverage (48/48) |
90-
| Debug API (`lua_Debug`) | 16% coverage (2/12) |
90+
| Debug API (`lua_Debug`) | 24% coverage (3/12) |
9191
| LuaJIT Extensions | *No plans to implement.* |
9292

9393
*†: Coroutine yield/resume is not yet part of the public `zig-luajit` Zig API, see [#6][ISSUE-6].*
@@ -283,7 +283,7 @@ This section describes the current status of Zig language bindings ("the Zig API
283283
| `lua_gethookmask` ||
284284
| `lua_gethook` ||
285285
| `lua_getlocal` ||
286-
| `lua_getstack` ||
286+
| `lua_getstack` | ☑️ `lua.getStack()` |
287287
| `lua_getupvalue` ||
288288
| `lua_sethook` ||
289289
| `lua_setlocal` ||

src/root.zig

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2784,6 +2784,23 @@ pub const Lua = opaque {
27842784
return 0 != c.lua_getinfo(asState(lua), what.ptr, @ptrCast(info));
27852785
}
27862786

2787+
/// Get information about the interpreter runtime stack. This function fills parts of a `DebugInfo` structure
2788+
/// with an identification of the activation record of the function executing at a given level. This function should
2789+
/// be called before calls to `getInfo()` when inspecting the call stack.
2790+
///
2791+
/// Level 0 is the current running function, whereas level 1 is the function that has called the current running
2792+
/// function, and so on.
2793+
///
2794+
/// Returns true when there are no errors, returns false otherwise. This function will return false when called
2795+
/// with a level greater than the stack depth, returns false.
2796+
///
2797+
/// From: `int lua_getstack(lua_State *L, int level, lua_Debug *ar);`
2798+
/// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_getstack
2799+
/// Stack Behavior: `[-0, +0, -]`
2800+
pub fn getStack(lua: *Lua, level: i32, info: *Lua.DebugInfo) bool {
2801+
return 0 != c.lua_getstack(asState(lua), level, @ptrCast(info));
2802+
}
2803+
27872804
/// Represents the different kinds of functions that can be inspected by `getInfo()`. This enumerates the possible
27882805
/// values that `getInfo()` will set in the `what` field when inspecting a function.
27892806
pub const FunctionKind = enum {
@@ -5474,3 +5491,48 @@ test "getInfoFunction() can pretty printed" {
54745491
\\
54755492
, actual[45..]);
54765493
}
5494+
5495+
test "getStack() can be used to inspect the call stack" {
5496+
const lua = try Lua.init(std.testing.allocator);
5497+
defer lua.deinit();
5498+
5499+
const T = struct {
5500+
fn errorCallback(l: *Lua) callconv(.c) i32 {
5501+
var info: Lua.DebugInfo = .{};
5502+
if (!l.getStack(1, &info) or !l.getInfo("nSlufL", &info)) {
5503+
return l.raiseErrorFormat("unreachable", .{});
5504+
}
5505+
5506+
std.testing.expectEqualStrings("bar\x00", info.name.?[0..4]) catch unreachable;
5507+
std.testing.expectEqualStrings("global\x00", info.namewhat.?[0..7]) catch unreachable;
5508+
std.testing.expectEqualStrings("Lua\x00", info.what.?[0..4]) catch unreachable;
5509+
std.testing.expectEqualStrings("[string \"function bar()...\"]\x00", info.short_src[0..29]) catch unreachable;
5510+
std.testing.expectEqual(2, info.currentline) catch unreachable;
5511+
std.testing.expectEqual(0, info.nups) catch unreachable;
5512+
std.testing.expectEqual(1, info.linedefined) catch unreachable;
5513+
std.testing.expectEqual(3, info.lastlinedefined) catch unreachable;
5514+
5515+
l.pushString(info.name.?);
5516+
return 1;
5517+
}
5518+
};
5519+
5520+
lua.pushCFunction(T.errorCallback);
5521+
const expected_source =
5522+
\\function bar()
5523+
\\ return error("this error invokes the errorCallback above")
5524+
\\end
5525+
\\function foo()
5526+
\\ bar()
5527+
\\end
5528+
;
5529+
try lua.doString(expected_source);
5530+
5531+
try std.testing.expectEqual(Lua.Type.function, lua.getGlobal("foo"));
5532+
try std.testing.expectError(Lua.ProtectedCallError.Runtime, lua.callProtected(0, Lua.MultipleReturn, 1));
5533+
5534+
try std.testing.expectEqual(2, lua.getTop());
5535+
try std.testing.expect(lua.isFunction(1));
5536+
try std.testing.expect(lua.isString(2));
5537+
try std.testing.expectEqualStrings("bar", try lua.toLString(-1));
5538+
}

0 commit comments

Comments
 (0)