Skip to content

Commit 21de06c

Browse files
committed
refactor: tidy return values and cleanup TODOs
1 parent 7e50803 commit 21de06c

File tree

3 files changed

+67
-67
lines changed

3 files changed

+67
-67
lines changed

docs.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ Because `error` is a reserved word in Zig, these functions have been renamed to
8484

8585
These functions have been combined into `Lua.toString()`. The function `lua_tostring` is a macro around `lua_tolstring` and does not return the length of the string.
8686

87+
### `lua_pushvfstring`
88+
89+
This function has been omitted because Zig does not have a va_list type, and `Lua.pushFString` works well
90+
enough for string formatting if variadic args are really needed.
91+
8792
The length of the returned string is almost always needed, so `Lua.toString() returns a zero-terminated Zig slice of the bytes with the correct length.
8893

8994
### `lua_tointegerx` and `lua_tonumberx`

src/tests.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn failing_alloc(data: ?*anyopaque, ptr: ?*anyopaque, osize: usize, nsize: usize
6666
test "initialization" {
6767
// initialize the Zig wrapper
6868
var lua = try Lua.init(testing.allocator);
69-
try expectEqual(Lua.StatusType.ok, lua.status());
69+
try expectEqual(ziglua.Status.ok, lua.status());
7070
lua.deinit();
7171

7272
// attempt to initialize the Zig wrapper with no memory
@@ -934,7 +934,7 @@ test "raise error" {
934934
try expectEqualStrings("makeError made an error", lua.toString(-1).?);
935935
}
936936

937-
fn continuation(l: *Lua, status: Lua.StatusType, ctx: isize) i32 {
937+
fn continuation(l: *Lua, status: ziglua.Status, ctx: isize) i32 {
938938
_ = status;
939939

940940
if (ctx == 5) {
@@ -968,11 +968,11 @@ test "yielding" {
968968
var results: i32 = undefined;
969969
var i: i32 = 0;
970970
while (i < 5) : (i += 1) {
971-
try expectEqual(Lua.ResumeStatus.yield, try thread.resumeThread(lua, 0, &results));
971+
try expectEqual(ziglua.ResumeStatus.yield, try thread.resumeThread(lua, 0, &results));
972972
try expectEqual(@as(Integer, i), thread.toInteger(-1));
973973
thread.pop(results);
974974
}
975-
try expectEqual(Lua.ResumeStatus.ok, try thread.resumeThread(lua, 0, &results));
975+
try expectEqual(ziglua.ResumeStatus.ok, try thread.resumeThread(lua, 0, &results));
976976
try expectEqualStrings("done", thread.toString(-1).?);
977977
}
978978

src/ziglua.zig

Lines changed: 58 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ pub const ArithOperator = enum(u4) {
4444

4545
/// Type for C functions
4646
/// See https://www.lua.org/manual/5.4/manual.html#lua_CFunction for the protocol
47-
/// TODO: we really are passing Zig functions, maybe call `Function` and use `func` for params?
4847
pub const CFn = fn (state: ?*LuaState) callconv(.C) c_int;
4948

5049
/// Operations supported by `Lua.compare()`
@@ -198,6 +197,12 @@ pub const Number = c.lua_Number;
198197
/// The type of the reader function used by `Lua.load()`
199198
pub const CReaderFn = fn (state: ?*LuaState, data: ?*anyopaque, size: [*c]usize) callconv(.C) [*c]const u8;
200199

200+
/// The possible status of a call to `Lua.resumeThread`
201+
pub const ResumeStatus = enum(u1) {
202+
ok = StatusCode.ok,
203+
yield = StatusCode.yield,
204+
};
205+
201206
/// Reference constants
202207
pub const ref_nil = c.LUA_REFNIL;
203208
pub const ref_no = c.LUA_NOREF;
@@ -211,24 +216,35 @@ pub const ridx_globals = c.LUA_RIDX_GLOBALS;
211216
/// Index of the main thread in the registry
212217
pub const ridx_mainthread = c.LUA_RIDX_MAINTHREAD;
213218

219+
/// Status that a thread can be in
220+
/// Usually errors are reported by a Zig error rather than a status enum value
221+
pub const Status = enum(u3) {
222+
ok = StatusCode.ok,
223+
yield = StatusCode.yield,
224+
err_runtime = StatusCode.err_runtime,
225+
err_syntax = StatusCode.err_syntax,
226+
err_memory = StatusCode.err_memory,
227+
err_error = StatusCode.err_error,
228+
};
229+
214230
/// Status codes
215231
/// Not public, because typically Status.ok is returned from a function implicitly;
216232
/// Any function that returns an error usually returns a Zig error, and a void return
217233
/// is an implicit Status.ok.
218234
/// In the rare case that the status code is required from a function, an enum is
219235
/// used for that specific function's return type
220-
const Status = struct {
236+
const StatusCode = struct {
221237
pub const ok = c.LUA_OK;
222238
pub const yield = c.LUA_YIELD;
223239
pub const err_runtime = c.LUA_ERRRUN;
224240
pub const err_syntax = c.LUA_ERRSYNTAX;
225241
pub const err_memory = c.LUA_ERRMEM;
226242
pub const err_error = c.LUA_ERRERR;
227-
228-
// Only used in loadFileX
229-
pub const err_file = c.LUA_ERRFILE;
230243
};
231244

245+
// Only used in loadFileX, so no need to group with Status
246+
pub const err_file = c.LUA_ERRFILE;
247+
232248
/// The standard representation for file handles used by the standard IO library
233249
pub const Stream = c.luaL_Stream;
234250

@@ -575,12 +591,12 @@ pub const Lua = struct {
575591
};
576592
const ret = c.lua_load(lua.state, reader, data, chunk_name, mode_str);
577593
switch (ret) {
578-
Status.ok => return,
579-
Status.err_syntax => return Error.Syntax,
580-
Status.err_memory => return Error.Memory,
581-
// can also return any result of a pcall error
582-
Status.err_runtime => return Error.Runtime,
583-
Status.err_error => return Error.MsgHandler,
594+
StatusCode.ok => return,
595+
StatusCode.err_syntax => return Error.Syntax,
596+
StatusCode.err_memory => return Error.Memory,
597+
// lua_load runs pcall, so can also return any result of an pcall error
598+
StatusCode.err_runtime => return Error.Runtime,
599+
StatusCode.err_error => return Error.MsgHandler,
584600
else => unreachable,
585601
}
586602
}
@@ -607,8 +623,6 @@ pub const Lua = struct {
607623
/// This function creates and pushes a new full userdata onto the stack
608624
/// with `num_uvalue` associated Lua values, plus an associated block of raw memory with `size` bytes
609625
/// Returns the address of the block of memory
610-
/// TODO: use comptime to return the a pointer to a block of type T for safety?
611-
/// See how this is used if that would be useful
612626
pub fn newUserdataUV(lua: *Lua, comptime T: type, new_uvalue: i32) *T {
613627
// safe to .? because this function throws a Lua error on out of memory
614628
// so the returned pointer should never be null
@@ -642,10 +656,10 @@ pub const Lua = struct {
642656
pub fn protectedCallCont(lua: *Lua, num_args: i32, num_results: i32, msg_handler: i32, ctx: KContext, k: ?CContFn) !void {
643657
const ret = c.lua_pcallk(lua.state, num_args, num_results, msg_handler, ctx, k);
644658
switch (ret) {
645-
Status.ok => return,
646-
Status.err_runtime => return Error.Runtime,
647-
Status.err_memory => return Error.Memory,
648-
Status.err_error => return Error.MsgHandler,
659+
StatusCode.ok => return,
660+
StatusCode.err_runtime => return Error.Runtime,
661+
StatusCode.err_memory => return Error.Memory,
662+
StatusCode.err_error => return Error.MsgHandler,
649663
else => unreachable,
650664
}
651665
}
@@ -737,8 +751,6 @@ pub const Lua = struct {
737751
c.lua_pushvalue(lua.state, index);
738752
}
739753

740-
// TODO: pub fn pushVFString is that even worth?
741-
742754
/// Returns true if the two values in indices `index1` and `index2` are primitively equal
743755
/// Bypasses __eq metamethods
744756
/// Returns false if not equal, or if any index is invalid
@@ -815,22 +827,17 @@ pub const Lua = struct {
815827
/// Resets a thread, cleaning its call stack and closing all pending to-be-closed variables
816828
/// Returns an error if an error occured and leaves an error object on top of the stack
817829
pub fn resetThread(lua: *Lua) !void {
818-
if (c.lua_resetthread(lua.state) != Status.ok) return Error.Fail;
830+
if (c.lua_resetthread(lua.state) != StatusCode.ok) return Error.Fail;
819831
}
820832

821-
pub const ResumeStatus = enum(u1) {
822-
ok = Status.ok,
823-
yield = Status.yield,
824-
};
825-
826833
/// Starts and resumes a coroutine in the given thread
827834
pub fn resumeThread(lua: *Lua, from: ?Lua, num_args: i32, num_results: *i32) !ResumeStatus {
828835
const from_state = if (from) |from_val| from_val.state else null;
829836
const thread_status = c.lua_resume(lua.state, from_state, num_args, num_results);
830837
switch (thread_status) {
831-
Status.err_runtime => return Error.Runtime,
832-
Status.err_memory => return Error.Memory,
833-
Status.err_error => return Error.MsgHandler,
838+
StatusCode.err_runtime => return Error.Runtime,
839+
StatusCode.err_memory => return Error.Memory,
840+
StatusCode.err_error => return Error.MsgHandler,
834841
else => return @intToEnum(ResumeStatus, thread_status),
835842
}
836843
}
@@ -897,19 +904,9 @@ pub const Lua = struct {
897904
c.lua_setwarnf(lua.state, warn_fn, data);
898905
}
899906

900-
// TODO: this is not very clean
901-
pub const StatusType = enum(u3) {
902-
ok = Status.ok,
903-
yield = Status.yield,
904-
err_runtime = Status.err_runtime,
905-
err_syntax = Status.err_syntax,
906-
err_memory = Status.err_memory,
907-
err_error = Status.err_error,
908-
};
909-
910907
/// Returns the status of this thread
911-
pub fn status(lua: *Lua) StatusType {
912-
return @intToEnum(StatusType, c.lua_status(lua.state));
908+
pub fn status(lua: *Lua) Status {
909+
return @intToEnum(Status, c.lua_status(lua.state));
913910
}
914911

915912
/// Converts the zero-terminated string `str` to a number, pushes that number onto the stack,
@@ -1037,16 +1034,18 @@ pub const Lua = struct {
10371034
c.lua_xmove(lua.state, to.state, num);
10381035
}
10391036

1040-
/// This function is equivalent to `Lua.yieldK()` but has no continuation
1041-
/// TODO: return values?
1042-
pub fn yield(lua: *Lua, num_results: i32) i32 {
1037+
/// This function is equivalent to `Lua.yieldCont()` but has no continuation
1038+
/// NOTE: look into the lua_yieldk docs about this and debug hooks and noreturn
1039+
pub fn yield(lua: *Lua, num_results: i32) noreturn {
10431040
// translate-c failed to pass NULL correctly
1044-
return c.lua_yieldk(lua.state, num_results, 0, null);
1041+
_ = c.lua_yieldk(lua.state, num_results, 0, null);
1042+
unreachable;
10451043
}
10461044

10471045
/// Yields this coroutine (thread)
1048-
pub fn yieldCont(lua: *Lua, num_results: i32, ctx: KContext, k: CContFn) i32 {
1049-
return c.lua_yieldk(lua.state, num_results, ctx, k);
1046+
pub fn yieldCont(lua: *Lua, num_results: i32, ctx: KContext, k: CContFn) noreturn {
1047+
_ = c.lua_yieldk(lua.state, num_results, ctx, k);
1048+
unreachable;
10501049
}
10511050

10521051
// Debug library functions
@@ -1325,24 +1324,25 @@ pub const Lua = struct {
13251324
};
13261325
const ret = c.luaL_loadfilex(lua.state, file_name, mode_str);
13271326
switch (ret) {
1328-
Status.ok => return,
1329-
Status.err_syntax => return Error.Syntax,
1330-
Status.err_memory => return Error.Memory,
1331-
Status.err_file => return Error.File,
1327+
StatusCode.ok => return,
1328+
StatusCode.err_syntax => return Error.Syntax,
1329+
StatusCode.err_memory => return Error.Memory,
1330+
err_file => return Error.File,
13321331
// NOTE: the docs mention possible other return types, but I couldn't figure them out
13331332
else => unreachable,
13341333
}
13351334
}
13361335

13371336
/// Loads a string as a Lua chunk
1338-
/// TODO: investigate what kind of return codes this really can return
13391337
pub fn loadString(lua: *Lua, str: [:0]const u8) !void {
13401338
const ret = c.luaL_loadstring(lua.state, str);
13411339
switch (ret) {
1342-
Status.ok => return,
1343-
Status.err_syntax => return Error.Syntax,
1344-
Status.err_memory => return Error.Memory,
1345-
// NOTE: loadstring calls lua_load which can return more status codes than this?
1340+
StatusCode.ok => return,
1341+
StatusCode.err_syntax => return Error.Syntax,
1342+
StatusCode.err_memory => return Error.Memory,
1343+
// loadstring runs lua_load which runs pcall, so can also return any result of an pcall error
1344+
StatusCode.err_runtime => return Error.Runtime,
1345+
StatusCode.err_error => return Error.MsgHandler,
13461346
else => unreachable,
13471347
}
13481348
}
@@ -1485,8 +1485,6 @@ pub const Lua = struct {
14851485
}
14861486

14871487
// Standard library loading functions
1488-
//
1489-
// TODO: opening libs can run arbitrary Lua code and can throw any error
14901488

14911489
/// Opens the specified standard library functions
14921490
/// Behaves like openLibs, but allows specifying which libraries
@@ -1582,9 +1580,7 @@ pub const Buffer = struct {
15821580

15831581
/// Adds `byte` to the buffer
15841582
pub fn addChar(buf: *Buffer, byte: u8) void {
1585-
// the postfix inc/dec expression is not yet supported by translate-c
1586-
// c.luaL_addchar(&buf.b, byte);
1587-
// TODO: revisit this once Zig bug is fixed (perhaps fix bug?)
1583+
// NOTE: could not be translated by translate-c
15881584
var lua_buf = &buf.b;
15891585
if (lua_buf.n >= lua_buf.size) _ = buf.prepSize(1);
15901586
lua_buf.b[lua_buf.n] = byte;
@@ -1674,7 +1670,7 @@ pub inline fn opaqueCast(comptime T: type, ptr: *anyopaque) *T {
16741670

16751671
pub const ZigFn = fn (lua: *Lua) i32;
16761672
pub const ZigHookFn = fn (lua: *Lua, ar: *DebugInfo) void;
1677-
pub const ZigContFn = fn (lua: *Lua, status: Lua.StatusType, ctx: KContext) i32;
1673+
pub const ZigContFn = fn (lua: *Lua, status: Status, ctx: KContext) i32;
16781674
pub const ZigReaderFn = fn (lua: *Lua, data: *anyopaque) ?[]const u8;
16791675
pub const ZigWarnFn = fn (data: ?*anyopaque, msg: []const u8, to_cont: bool) void;
16801676
pub const ZigWriterFn = fn (lua: *Lua, buf: []const u8, data: *anyopaque) bool;
@@ -1716,7 +1712,6 @@ fn wrapZigFn(comptime f: ZigFn) CFn {
17161712
fn inner(state: ?*LuaState) callconv(.C) c_int {
17171713
// this is called by Lua, state should never be null
17181714
var lua: Lua = .{ .state = state.? };
1719-
// TODO: should we pass a pointer to the lua state? no real reason to
17201715
return @call(.{ .modifier = .always_inline }, f, .{&lua});
17211716
}
17221717
}.inner;
@@ -1739,7 +1734,7 @@ fn wrapZigContFn(comptime f: ZigContFn) CContFn {
17391734
fn inner(state: ?*LuaState, status: c_int, ctx: KContext) callconv(.C) c_int {
17401735
// this is called by Lua, state should never be null
17411736
var lua: Lua = .{ .state = state.? };
1742-
return @call(.{ .modifier = .always_inline }, f, .{ &lua, @intToEnum(Lua.StatusType, status), ctx });
1737+
return @call(.{ .modifier = .always_inline }, f, .{ &lua, @intToEnum(Status, status), ctx });
17431738
}
17441739
}.inner;
17451740
}

0 commit comments

Comments
 (0)