-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: port dbg!()
from Rust
#3296
Comments
You can write this today as normal zig code: fn dbg(comptime T: type, value: T) T {
if (builtin.mode == builtin.Mode.Debug) {
std.debug.warn("{}", value);
}
return value;
} I think |
It may work (especially with
I indent this to be a trading maintainability for quick modification-series feature, maybe available only in special mode, so ergonomy is a priority. |
Would this not be closer to the original proposal? var warned = false;
fn dbg(value: anyvalue) @TypeOf(value) {
std.debug.warn("[dbg]: {}", value);
return value;
} |
@nektro what's |
They probably meant |
You can get the expression too and the result isn't too far from the proposal though for blocks it'd require a bit more work to get the display right. Result:
Code (it's not pretty): original.zig const dbg = @import("example.zig").dbg;
test {
_ = foo(11);
}
fn foo(x: u64) u32 {
var a: u64 = switch (x) {
4 => 4,
0...3 => 8 * x + (x << 4) * 3,
5...10 => 5 * x + (x << 2) * 3,
11...19 => dbg(@src(), 2 * x + x * x),
else => 0xFFFFFFFF,
};
return @intCast(u32, (((a * a) % 4294967291) * a) % 4294967291);
} example.zig const std = @import("std");
const mem = std.mem;
pub fn dbg(comptime loc: std.builtin.SourceLocation, val: anytype) @TypeOf(val) {
var src = @embedFile(loc.file);
var start: usize = 0;
var line: usize = 0;
while (mem.indexOfScalarPos(u8, src, start, '\n')) |pos| {
line += 1;
if (line >= loc.line) break;
start = pos + 1;
}
start += loc.column - 1;
var it = std.zig.Tokenizer.init(src[start..]);
const code_start = start + while (true) {
const token = it.next();
if (token.tag == .comma) break it.index;
} else unreachable;
var depth: usize = 0;
const code_end = start + while (true) {
const token = it.next();
switch (token.tag) {
.r_paren => if (depth != 0) {
depth -= 1;
} else break it.index,
.l_paren => depth += 1,
else => {},
}
} else unreachable;
std.debug.print("[{s}:{d}] {s} = {any}\n", .{
loc.file,
loc.line,
src[code_start..code_end - 1],
val,
});
return val;
}
test {
_ = dbg(@src(), @as(u32, (4 + 5) + 9));
} |
Some more thoughts on this:
Here's roughly how I imagine it: pub fn main() void {
var x: u8 = 5;
@dbg("hello", x + 1, 123 * 5);
}
All expressions are on separate lines and all lines only of the same This means now we would be able to write hello worlds without the std, which might feel weird but I think it's ok because it's not a production-ready hello world anyway and you can only use it in debug mode. And of course this compile-errors in any environment without an stderr available. |
proof of concept https://gist.github.com/nektro/f363b7e6d72885e6d7b9a57e76c47c12 |
@nektro , This one seems to rely on stack walking and availability of symbols, so may break in embedded or exotic scenarios. Another approach is to embed caller information into the format string itself at compile time. As far as I understand, Rust uses this approach and have special annotation for functions that would redirect Rust's analogue of |
Primary tool for "printf debugging" in Zig seems to be
std.debug.warn
. This works, but cumbersome for some use cases where you want to temporarily insert tracing of some [sub]expression without chaning the code around too much.For example, you have this code:
Now you want to see what's the value of
2*x + x*x
and how often is it called (without being bothered by other switch branches).It is 10 additional things to think of (
blk:
,{}
block,var
, new identifier namexx
,warn
, format string that is identifiable among other output, not forgotten\n
,break
,:blk
, final semicolon before}
) just for trivial one-off debug run.This should be nicer. Therefore I propose to adopt
dbg!(x)
approach from Rust.This is what it should look like:
Filename (or filepath) is included
Line number
Citation from source code
Actual value, if it can ever be printed;
No import needed (nice to have)
Semantically
@dbg
acts like an identity function (fn dbg(x: var) @typeOf(x) { return x; }
)Such function should be either dummied out (turns an into actual identity function) or just forbidden for non-debug usages (
--sloppy
mode only). Obviously, this rule should not be tangled with LLVM optimisation level.See also: #2029.
The text was updated successfully, but these errors were encountered: