Skip to content

Commit fcf6d9e

Browse files
committed
Add support for lua.raiseErrorFormat
1 parent ec0e790 commit fcf6d9e

File tree

3 files changed

+51
-25
lines changed

3 files changed

+51
-25
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ you.
8686
| API | Support |
8787
|-----------------------------|---------------------------------------|
8888
| Lua C API (`lua_*`) | 🎉 100% coverage<sup>†</sup> (92/92) |
89-
| Auxilary Library (`luaL_*`) | 44% coverage (23/48) |
89+
| Auxilary Library (`luaL_*`) | 48% coverage (24/48) |
9090
| LuaJIT Extensions | *No plans to implement.* |
9191

9292
*†: Coroutine yield/resume is not yet part of the public `zig-luajit` Zig API, see [#6][ISSUE-6].*
@@ -245,7 +245,7 @@ The `zig-luajit` project has not yet reached the 1.0 release, the API is subject
245245
| `luaL_checkudata` |`lua.checkUserdata()`|
246246
| `luaL_dofile` ||
247247
| `luaL_dostring` | ☑️ `lua.doString()` |
248-
| `luaL_error` ||
248+
| `luaL_error` | ☑️📢 `lua.raiseErrorFormat()` |
249249
| `luaL_getmetafield` ||
250250
| `luaL_getmetatable` ||
251251
| `luaL_gsub` ||

src/lual_api.zig

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,6 @@ pub fn doFile(lua: *Lua, filename: [*:0]const u8) LuaError!void;
9090

9191

9292

93-
/// Raises an error with the given error message format and optional arguments. The error message follows
94-
/// the same rules as lua_pushfstring and includes the file name and line number where the error occurred,
95-
/// if such information is available. This function never returns.
96-
///
97-
/// From: `int luaL_error(lua_State *L, const char *fmt, ...);`
98-
/// Refer to: https://www.lua.org/manual/5.1/manual.html#luaL_error
99-
/// Stack Behavior: `[-0, +0, v]`
100-
pub fn lError(lua: *Lua, comptime fmt: []const u8, ...) noreturn;
101-
10293
/// Pushes onto the stack the field `e` from the metatable of the object at index `obj`.
10394
/// If the object does not have a metatable, or if the metatable does not have this field,
10495
/// returns 0 and pushes nothing.

src/root.zig

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -904,13 +904,11 @@ pub const Lua = opaque {
904904
/// * '%d' - Insert a `Lua.Integer`, usually an `i64`, and
905905
/// * '%c' - Insert a single character represented by a number.
906906
///
907-
/// **Usage of this function is discouraged**, consider instead using Zig `std.fmt` primitives in combination with
908-
/// `lua.pushString()` or `lua.pushLString()`.
909-
///
907+
/// See also: `raiseErrorFormat()`
910908
/// From: `const char *lua_pushfstring(lua_State *L, const char *fmt, ...);`
911909
/// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_pushfstring
912910
/// Stack Behavior: `[-0, +1, m]`
913-
pub fn pushFString(lua: *Lua, comptime format: []const u8, args: anytype) [:0]const u8 {
911+
pub fn pushFString(lua: *Lua, comptime format: [:0]const u8, args: anytype) [:0]const u8 {
914912
const string: ?[*:0]const u8 = @call(.auto, c.lua_pushfstring, .{ asState(lua), format.ptr } ++ args);
915913
if (string) |s| {
916914
// NOTE: This seems dangerous. I don't really like this solution, but it doesn't look like there is any other option.
@@ -1472,10 +1470,8 @@ pub const Lua = opaque {
14721470
return 1 == c.lua_next(asState(lua), index);
14731471
}
14741472

1475-
/// Generates a Lua error. The error message (which can actually be a Lua value of any type)
1476-
/// must be on the stack top. This function does a long jump and therefore never returns.
1477-
///
1478-
/// Note: This function was renamed from `error` due to naming conflicts with Zig's `error` keyword.
1473+
/// Raises an error with the error message on the top of the stack. The error message may be a Lua value of any
1474+
/// type, but usually a string is best. This function does a long jump and therefore never returns.
14791475
///
14801476
/// From: `int lua_error(lua_State *L);`
14811477
/// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_error
@@ -1485,6 +1481,27 @@ pub const Lua = opaque {
14851481
unreachable;
14861482
}
14871483

1484+
/// Raises an error with the given error message format and optional arguments. The error message follows
1485+
/// the same rules as `pushFString()` and includes the file name and line number where the error occurred,
1486+
/// if such information is available. This function does a long jump and therefore never returns.
1487+
///
1488+
/// In the given `format` string, format specifiers are restricted to the following options:
1489+
/// * '%%' - Insert a literal '%' character in the string.
1490+
/// * '%s' - Insert a zero-terminated string,
1491+
/// * '%f' - Insert a `Lua.Number`, usually an `f64`,
1492+
/// * '%p' - Insert a pointer-width ineger formatted as hexadecimal,
1493+
/// * '%d' - Insert a `Lua.Integer`, usually an `i64`, and
1494+
/// * '%c' - Insert a single character represented by a number.
1495+
///
1496+
/// See also: `pushFString()`
1497+
/// From: `int luaL_error(lua_State *L, const char *fmt, ...);`
1498+
/// Refer to: https://www.lua.org/manual/5.1/manual.html#luaL_error
1499+
/// Stack Behavior: `[-0, +0, v]`
1500+
pub fn raiseErrorFormat(lua: *Lua, format: [:0]const u8, args: anytype) noreturn {
1501+
_ = @call(.auto, c.luaL_error, .{ asState(lua), format.ptr } ++ args);
1502+
unreachable;
1503+
}
1504+
14881505
/// Represents the kinds of errors that calling a Lua function may result in.
14891506
pub const CallError = error{
14901507
/// Used when the execution of Lua code encounters an error.
@@ -2779,19 +2796,37 @@ test "c functions and closures with protectedCall" {
27792796
lua.pop(1);
27802797
}
27812798

2782-
fn errorRaisingCFunction(lua: *Lua) callconv(.c) i32 {
2783-
lua.pushLString("error raised");
2784-
lua.raiseError();
2799+
test "protectedCall should capture error raised by c function" {
2800+
const lua = try Lua.init(std.testing.allocator);
2801+
defer lua.deinit();
2802+
2803+
const T = struct {
2804+
fn errorRaisingCFunction(l: *Lua) callconv(.c) i32 {
2805+
l.pushLString("error raised");
2806+
l.raiseError();
2807+
}
2808+
};
2809+
2810+
lua.pushCFunction(T.errorRaisingCFunction);
2811+
const actual = lua.protectedCall(0, 0, 0);
2812+
try std.testing.expectError(Lua.CallError.Runtime, actual);
2813+
try std.testing.expectEqualSlices(u8, "error raised", try lua.toLString(-1));
27852814
}
27862815

2787-
test "c functions raising error with protectedCall" {
2816+
test "protectedCall should capture formatted error raised by c function" {
27882817
const lua = try Lua.init(std.testing.allocator);
27892818
defer lua.deinit();
27902819

2791-
lua.pushCFunction(errorRaisingCFunction);
2820+
const T = struct {
2821+
fn formattedErrorRaisingCFunction(l: *Lua) callconv(.c) i32 {
2822+
return l.raiseErrorFormat("%%-%s-%%,%f,%d,'%c'", .{ "Hello", @as(f64, 13.3), @as(i32, 42), @as(u8, 'A') });
2823+
}
2824+
};
2825+
2826+
lua.pushCFunction(T.formattedErrorRaisingCFunction);
27922827
const actual = lua.protectedCall(0, 0, 0);
27932828
try std.testing.expectError(Lua.CallError.Runtime, actual);
2794-
try std.testing.expectEqualSlices(u8, "error raised", try lua.toLString(-1));
2829+
try std.testing.expectEqualSlices(u8, "%-Hello-%,13.3,42,'A'", try lua.toLString(-1));
27952830
}
27962831

27972832
test "openLibs doesn't effect the stack" {

0 commit comments

Comments
 (0)