@@ -53,8 +53,64 @@ pub const CompareOperator = enum(u2) {
53
53
le = c .LUA_OPLE ,
54
54
};
55
55
56
+ /// The internal Lua debug structure
57
+ const Debug = c .lua_Debug ;
58
+
56
59
/// The Lua debug interface structure
57
- pub const DebugInfo = c .lua_Debug ;
60
+ pub const DebugInfo = struct {
61
+ source : [:0 ]const u8 = undefined ,
62
+ src_len : usize = 0 ,
63
+ short_src : [c .LUA_IDSIZE :0 ]u8 = undefined ,
64
+
65
+ name : ? [:0 ]const u8 = undefined ,
66
+ name_what : NameType = undefined ,
67
+ what : FnType = undefined ,
68
+
69
+ current_line : ? i32 = null ,
70
+ first_line_defined : ? i32 = null ,
71
+ last_line_defined : ? i32 = null ,
72
+
73
+ num_upvalues : u8 = 0 ,
74
+ num_params : u8 = 0 ,
75
+
76
+ is_vararg : bool = false ,
77
+ is_tail_call : bool = false ,
78
+
79
+ first_transfer : u16 = 0 ,
80
+ num_transfer : u16 = 0 ,
81
+
82
+ private : * anyopaque = undefined ,
83
+
84
+ pub const NameType = enum { global , local , method , field , upvalue , other };
85
+
86
+ pub const FnType = enum { lua , c , main };
87
+
88
+ pub const Options = packed struct {
89
+ @">" : bool = false ,
90
+ f : bool = false ,
91
+ l : bool = false ,
92
+ n : bool = false ,
93
+ r : bool = false ,
94
+ S : bool = false ,
95
+ t : bool = false ,
96
+ u : bool = false ,
97
+ L : bool = false ,
98
+
99
+ fn toString (options : Options ) [10 :0 ]u8 {
100
+ var str = [_ :0 ]u8 {0 } ** 10 ;
101
+ var index : u8 = 0 ;
102
+
103
+ inline for (std .meta .fields (Options )) | field | {
104
+ if (@field (options , field .name )) {
105
+ str [index ] = field .name [0 ];
106
+ index += 1 ;
107
+ }
108
+ }
109
+
110
+ return str ;
111
+ }
112
+ };
113
+ };
58
114
59
115
/// The superset of all errors returned from ziglua
60
116
pub const Error = error {
@@ -72,6 +128,15 @@ pub const Error = error{
72
128
File ,
73
129
};
74
130
131
+ /// The type of event that triggers a hook
132
+ pub const Event = enum (u3 ) {
133
+ call = c .LUA_HOOKCALL ,
134
+ ret = c .LUA_HOOKRET ,
135
+ line = c .LUA_HOOKLINE ,
136
+ count = c .LUA_HOOKCOUNT ,
137
+ tail_call = c .LUA_HOOKTAILCALL ,
138
+ };
139
+
75
140
/// Type for arrays of functions to be registered
76
141
pub const FnReg = struct {
77
142
name : [:0 ]const u8 ,
@@ -92,7 +157,7 @@ pub const GCAction = enum(u5) {
92
157
};
93
158
94
159
/// Type for debugging hook functions
95
- pub const CHookFn = fn (state : ? * LuaState , ar : ? * DebugInfo ) callconv (.C ) void ;
160
+ pub const CHookFn = fn (state : ? * LuaState , ar : ? * Debug ) callconv (.C ) void ;
96
161
97
162
/// Specifies on which events the hook will be called
98
163
pub const HookMask = packed struct {
@@ -1060,22 +1125,72 @@ pub const Lua = struct {
1060
1125
}
1061
1126
1062
1127
/// Gets information about a specific function or function invocation
1063
- /// TODO: look at possible types for what
1064
- pub fn getInfo (lua : * Lua , what : [:0 ]const u8 , ar : * DebugInfo ) bool {
1065
- return c .lua_getinfo (lua .state , what , ar ) != 0 ;
1128
+ /// Returns an error if an invalid option was given, but the valid options
1129
+ /// are still handled
1130
+ pub fn getInfo (lua : * Lua , options : DebugInfo.Options ) DebugInfo {
1131
+ const str = options .toString ();
1132
+ var ar : Debug = undefined ;
1133
+
1134
+ // should never fail because we are controlling options with the struct param
1135
+ std .debug .assert (c .lua_getinfo (lua .state , & str , & ar ) != 0 );
1136
+
1137
+ // copy data into a struct
1138
+ var info : DebugInfo = undefined ;
1139
+ if (options .l ) info .current_line = if (ar .currentline == -1 ) null else ar .currentline ;
1140
+ if (options .n ) {
1141
+ info .name = if (ar .name != null ) std .mem .span (ar .name ) else null ;
1142
+ info .name_what = blk : {
1143
+ const what = std .mem .span (ar .namewhat );
1144
+ if (std .mem .eql (u8 , "global" , what )) break :blk .global ;
1145
+ if (std .mem .eql (u8 , "local" , what )) break :blk .local ;
1146
+ if (std .mem .eql (u8 , "method" , what )) break :blk .method ;
1147
+ if (std .mem .eql (u8 , "field" , what )) break :blk .field ;
1148
+ if (std .mem .eql (u8 , "upvalue" , what )) break :blk .upvalue ;
1149
+ if (what .len == 0 ) break :blk .other ;
1150
+ unreachable ;
1151
+ };
1152
+ }
1153
+ if (options .r ) {
1154
+ info .first_transfer = ar .ftransfer ;
1155
+ info .num_transfer = ar .ntransfer ;
1156
+ }
1157
+ if (options .S ) {
1158
+ info .source = std .mem .span (ar .source );
1159
+ std .mem .copy (u8 , & info .short_src , & ar .short_src );
1160
+ info .first_line_defined = ar .linedefined ;
1161
+ info .last_line_defined = ar .lastlinedefined ;
1162
+ info .what = blk : {
1163
+ const what = std .mem .span (ar .what );
1164
+ if (std .mem .eql (u8 , "Lua" , what )) break :blk .lua ;
1165
+ if (std .mem .eql (u8 , "C" , what )) break :blk .c ;
1166
+ if (std .mem .eql (u8 , "main" , what )) break :blk .main ;
1167
+ unreachable ;
1168
+ };
1169
+ }
1170
+ if (options .t ) info .is_tail_call = ar .istailcall != 0 ;
1171
+ if (options .u ) {
1172
+ info .num_upvalues = ar .nups ;
1173
+ info .num_params = ar .nparams ;
1174
+ info .is_vararg = ar .isvararg != 0 ;
1175
+ }
1176
+ return info ;
1066
1177
}
1067
1178
1068
1179
/// Gets information about a local variable
1069
- pub fn getLocal (lua : * Lua , ar : * DebugInfo , n : i32 ) ! [:0 ]const u8 {
1070
- if (c .lua_getlocal (lua .state , ar , n )) | name | {
1180
+ pub fn getLocal (lua : * Lua , info : * DebugInfo , n : i32 ) ! [:0 ]const u8 {
1181
+ var ar : Debug = undefined ;
1182
+ ar .i_ci = @ptrCast (* c .struct_CallInfo , info .private );
1183
+ if (c .lua_getlocal (lua .state , & ar , n )) | name | {
1071
1184
return std .mem .span (name );
1072
1185
}
1073
1186
return Error .Fail ;
1074
1187
}
1075
1188
1076
1189
/// Gets information about the interpreter runtime stack
1077
- pub fn getStack (lua : * Lua , level : i32 , ar : * DebugInfo ) bool {
1078
- return c .lua_getstack (lua .state , level , ar ) != 0 ;
1190
+ pub fn getStack (lua : * Lua , level : i32 ) ! DebugInfo {
1191
+ var ar : Debug = undefined ;
1192
+ if (c .lua_getstack (lua .state , level , & ar ) == 0 ) return Error .Fail ;
1193
+ return DebugInfo { .private = ar .i_ci .? };
1079
1194
}
1080
1195
1081
1196
/// Gets information about the `n`th upvalue of the closure at index `func_index`
@@ -1094,8 +1209,10 @@ pub const Lua = struct {
1094
1209
1095
1210
/// Sets the value of a local variable
1096
1211
/// Returns an error when the index is greater than the number of active locals
1097
- pub fn setLocal (lua : * Lua , ar : * DebugInfo , n : i32 ) ! [:0 ]const u8 {
1098
- if (c .lua_setlocal (lua .state , ar , n )) | name | {
1212
+ pub fn setLocal (lua : * Lua , info : * DebugInfo , n : i32 ) ! [:0 ]const u8 {
1213
+ var ar : Debug = undefined ;
1214
+ ar .i_ci = @ptrCast (* c .struct_CallInfo , info .private );
1215
+ if (c .lua_setlocal (lua .state , & ar , n )) | name | {
1099
1216
return std .mem .span (name );
1100
1217
}
1101
1218
return Error .Fail ;
@@ -1660,7 +1777,7 @@ pub inline fn opaqueCast(comptime T: type, ptr: *anyopaque) *T {
1660
1777
}
1661
1778
1662
1779
pub const ZigFn = fn (lua : * Lua ) i32 ;
1663
- pub const ZigHookFn = fn (lua : * Lua , ar : * DebugInfo ) void ;
1780
+ pub const ZigHookFn = fn (lua : * Lua , event : Event , info : * DebugInfo ) void ;
1664
1781
pub const ZigContFn = fn (lua : * Lua , status : Status , ctx : Context ) i32 ;
1665
1782
pub const ZigReaderFn = fn (lua : * Lua , data : * anyopaque ) ? []const u8 ;
1666
1783
pub const ZigWarnFn = fn (data : ? * anyopaque , msg : []const u8 , to_cont : bool ) void ;
@@ -1711,10 +1828,14 @@ fn wrapZigFn(comptime f: ZigFn) CFn {
1711
1828
/// Wrap a ZigHookFn in a CHookFn for passing to the API
1712
1829
fn wrapZigHookFn (comptime f : ZigHookFn ) CHookFn {
1713
1830
return struct {
1714
- fn inner (state : ? * LuaState , ar : * DebugInfo ) callconv (.C ) void {
1831
+ fn inner (state : ? * LuaState , ar : ? * Debug ) callconv (.C ) void {
1715
1832
// this is called by Lua, state should never be null
1716
1833
var lua : Lua = .{ .state = state .? };
1717
- @call (.{ .modifier = .always_inline }, f , .{ & lua , ar .? });
1834
+ var info : DebugInfo = .{
1835
+ .current_line = if (ar .? .currentline == -1 ) null else ar .? .currentline ,
1836
+ .private = ar .i_ci ,
1837
+ };
1838
+ @call (.{ .modifier = .always_inline }, f , .{ & lua , @intToEnum (Event , ar .? .event ), info });
1718
1839
}
1719
1840
}.inner ;
1720
1841
}
0 commit comments