On Thursday, July 24, 2014 9:51:57 PM UTC+2, Tim Holy wrote: > On Thursday, July 24, 2014 12:09:59 PM Magnus Lie Hetland wrote: > > I saw a mention of a @debug macro somewhere on this list, > > which I assume doesn't exist either? > > @debug is alive and well in Toivo's amazing Debug.jl package. But since > debugging will change radically once Keno's work lands, I wouldn't worry > building a common infrastructure for both @assert and @debug. >
Ah, right. Awesome stuff :-) But it's quite different from what I meant – I was just thinking of a macro for marking code that would be nulled/removed if we're not running in debug mode (or whatever you want to call it). So that assertions would be just a special case. I guess this is sort of what -DNDEBUG (or, for that matter, -DDEBUG) in C/C++, or the __debug__ constant in Python <https://docs.python.org/3/library/constants.html>, is used for. (Slightly rambling email below…) The Python setup is basically that __debug__ is true if you start Python without the -O switch. The assert statement <https://docs.python.org/3/reference/simple_stmts.html#assert>, then, is then wrapped in an if __debug__ statement. This seems to me to be a conservative and sensible setup, which could be separate from Debug.jl, though, of course, if we had something like __debug__, it would be possible for Debug.jl to use that to switch things off. I guess the “magic names” of Python aren't that appropriate; perhaps it could simply be Base.debug? There would really be no reason for the kind of @debug macro I was talking about, as one could just use if statements (as in Python), without any overhead … maybe? Maybe not? Seems OK for simple cases: *julia> **const debug = false* *false* *julia> **f() = if debug 42 else 41 end* *f (generic function with 1 method)* *julia> **code_llvm(f, ())* define i64 @"julia_f;18972"() { top: ret i64 41, !dbg !772 } But if I add some more … *julia> **function f()* * if debug* * print("Debug!")* * end* * 41* *end* *f (generic function with 1 method)* *julia> **code_llvm(f, ())* define i64 @"julia_f;18980"() { top: %0 = alloca [4 x %jl_value_t*], align 8 %.sub = getelementptr inbounds [4 x %jl_value_t*]* %0, i64 0, i64 0 store %jl_value_t* inttoptr (i64 4 to %jl_value_t*), %jl_value_t** %.sub, align 8 %1 = load %jl_value_t*** @jl_pgcstack, align 8, !dbg !796 %2 = getelementptr [4 x %jl_value_t*]* %0, i64 0, i64 1, !dbg !796 %.c = bitcast %jl_value_t** %1 to %jl_value_t*, !dbg !796 store %jl_value_t* %.c, %jl_value_t** %2, align 8, !dbg !796 store %jl_value_t** %.sub, %jl_value_t*** @jl_pgcstack, align 8, !dbg !796 %3 = getelementptr [4 x %jl_value_t*]* %0, i64 0, i64 2 store %jl_value_t* null, %jl_value_t** %3, align 8 %4 = getelementptr [4 x %jl_value_t*]* %0, i64 0, i64 3 store %jl_value_t* null, %jl_value_t** %4, align 8 %5 = load %jl_value_t** %2, align 8, !dbg !797 %6 = getelementptr inbounds %jl_value_t* %5, i64 0, i32 0, !dbg !797 store %jl_value_t** %6, %jl_value_t*** @jl_pgcstack, align 8, !dbg !797 ret i64 41, !dbg !797 } I can see that this might be left to LLVM, but the native code for the two is still pretty different. So … it seems the if-statement does give some overhead? In that case, we might need some macro anyway, for this kind of functionality, perhaps. Maybe @ifdebug? I don't know. Initially, I guess having just a global constant indicating whether we are in a more tentative mode of running the code (whether we call it debug or something else) or if we're running things in a more optimized setting, coupled with a code-expansion-level if-statement for @assert (and a runtime if-statement for assert) would be an OK start. Judging by the precedence established by the current switches (such as --check-bounds={yes|no}) perhaps making the functionality more specific might even be desired, I guess, and limiting this to *only* assertions, with --assertions={yes|no}, perhaps? Less stepping on Debug.jl's (or LLVM dbg's) toes, maybe?
