@@ -806,12 +806,13 @@ pub const Lua = opaque {
806806 /// Stack Behavior: `[-1, +1, e]`
807807 pub fn getTable (lua : * Lua , index : i32 ) Lua.Type {
808808 lua .validateStackIndex (index );
809+ assert (lua .isTable (index ));
809810
810811 c .lua_gettable (asState (lua ), index );
811812 return lua .typeOf (-1 );
812813 }
813814
814- /// Similar to lua_gettable , but does a raw access (i.e., without metamethods) .
815+ /// Similar to `getTable()` , but this implementation will not invoke any metamethods.
815816 ///
816817 /// Note: This function was renamed from `rawget`.
817818 ///
@@ -825,6 +826,19 @@ pub const Lua = opaque {
825826 return lua .typeOf (-1 );
826827 }
827828
829+ /// Pushes onto the stack the metatable of the value at the given acceptable index. If the index is not
830+ /// valid, or if the value does not have a metatable, the function returns `false` and pushes nothing on
831+ /// the stack.
832+ ///
833+ /// From: `int lua_getmetatable(lua_State *L, int index);`
834+ /// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_getmetatable
835+ /// Stack Behavior: `[-0, +(0|1), -]`
836+ pub fn getMetatable (lua : * Lua , index : i32 ) bool {
837+ lua .validateStackIndex (index );
838+
839+ return 1 == c .lua_getmetatable (asState (lua ), index );
840+ }
841+
828842 /// Does the equivalent of `t[k] = v`, where `t` is the acceptable index of the table on the stack, `v` is
829843 /// the value at the top of the stack, and `k` is the value just below the top. This function pops both the
830844 /// key and the value from the stack. As in Lua, this function may trigger a metamethod for the "newindex"
@@ -850,6 +864,20 @@ pub const Lua = opaque {
850864 return c .lua_settable (asState (lua ), index );
851865 }
852866
867+ /// Pops a table from the top of the stack and sets it as the metatable for the value at the
868+ /// given acceptable index.
869+ ///
870+ /// From: `int lua_setmetatable(lua_State *L, int index);`
871+ /// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_setmetatable
872+ /// Stack Behavior: `[-1, +0, -]`
873+ pub fn setMetatable (lua : * Lua , index : i32 ) void {
874+ lua .validateStackIndex (index );
875+ assert (lua .isTable (index ));
876+
877+ const res = c .lua_setmetatable (asState (lua ), index );
878+ assert (1 == res );
879+ }
880+
853881 /// Pops `n` elements from the stack.
854882 ///
855883 /// From: `void lua_pop(lua_State *L, int n);`
@@ -871,6 +899,19 @@ pub const Lua = opaque {
871899 return c .lua_gettop (asState (lua ));
872900 }
873901
902+ /// Accepts any acceptable index, or 0, and sets the stack top to this index. If the new top is
903+ /// larger than the old one, then the new elements are filled with nil. If index is 0, then all
904+ /// stack elements are removed.
905+ ///
906+ /// From: `void lua_settop(lua_State *L, int index);`
907+ /// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_settop
908+ /// Stack Behavior: `[-?, +?, -]`
909+ pub fn setTop (lua : * Lua , index : i32 ) void {
910+ assert (index >= 0 );
911+
912+ return c .lua_settop (asState (lua ), index );
913+ }
914+
874915 /// Moves the top element into the given valid index, shifting up the elements above this index to open space.
875916 /// Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.
876917 ///
@@ -1069,13 +1110,13 @@ pub const Lua = opaque {
10691110 assert (Status .is_status (res )); // Expected the status to be one of the "thread status" values defined in lua.h
10701111
10711112 const s : Status = @enumFromInt (res );
1072- return switch (s ) {
1113+ switch (s ) {
10731114 .ok = > return ,
1074- .runtime_error = > error .Runtime ,
1075- .memory_error = > error .OutOfMemory ,
1076- .error_handling_error = > error .ErrorHandlerFailure ,
1115+ .runtime_error = > return error .Runtime ,
1116+ .memory_error = > return error .OutOfMemory ,
1117+ .error_handling_error = > return error .ErrorHandlerFailure ,
10771118 else = > std .debug .panic ("Lua returned unexpected status code from protected call: {d}\n " , .{res }),
1078- };
1119+ }
10791120 }
10801121
10811122 /// Opens all standard Lua libraries into the given state. Callers may prefer to open individual
@@ -1939,3 +1980,49 @@ test "concat should follow expected semantics" {
19391980 try std .testing .expectEqualSlices (u8 , "42-84-Boof" , try lua .toLString (-1 ));
19401981 lua .pop (1 );
19411982}
1983+
1984+ fn always42AddMetamethod (lua : * Lua ) callconv (.c ) i32 {
1985+ lua .pushInteger (42 );
1986+ return 1 ;
1987+ }
1988+
1989+ test "metatables can be set" {
1990+ const lua = try Lua .init (std .testing .allocator );
1991+ defer lua .deinit ();
1992+
1993+ lua .openBaseLib ();
1994+
1995+ lua .newTable ();
1996+ lua .newTable ();
1997+ lua .pushLString ("__add" );
1998+ lua .pushCFunction (always42AddMetamethod );
1999+ lua .setTable (-3 );
2000+ lua .setMetatable (-2 );
2001+
2002+ try std .testing .expect (lua .getMetatable (-1 ));
2003+ try std .testing .expect (lua .isTable (-1 ));
2004+ lua .setTop (0 );
2005+ }
2006+
2007+ test "metatables can be accessed" {
2008+ const lua = try Lua .init (std .testing .allocator );
2009+ defer lua .deinit ();
2010+
2011+ lua .openBaseLib ();
2012+
2013+ try lua .doString (
2014+ \\f = {}
2015+ \\return setmetatable(f, {
2016+ \\ __add = function (l, r)
2017+ \\ return 0
2018+ \\ end
2019+ \\})
2020+ );
2021+ try std .testing .expect (lua .isTable (-1 ));
2022+ try std .testing .expect (lua .getMetatable (-1 ));
2023+ try std .testing .expect (lua .isTable (-1 ));
2024+
2025+ lua .pushLString ("__add" );
2026+ try std .testing .expectEqual (Lua .Type .function , lua .getTable (-2 ));
2027+ lua .setTop (0 );
2028+ }
0 commit comments