June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to Unknown W. Brackets | On Wed, 31 May 2006 21:38:04 -0700, Unknown W. Brackets wrote: > Walter, > > My most common use for having this is simple... Excellent reply and I'm now convinced too. As a heretical aside, with the almost released new version of Build, you can do something like the C-styled assert macro. You can define a macro replacement pattern such as ... regexp <:assert\s(.*)::(.*):> = if (!($1)) {writefln(`%%s:%%s`, `$1`, `$2`); assert(0);} and then write in your code ... <:assert result != 0::Bad result:> which will transform into ... if (!(result != 0)) {writefln(`%s:%s`, `result != 0`, `Bad result`); assert(0);} -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 1/06/2006 3:48:31 PM |
June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Derek Parnell wrote:
> On Wed, 31 May 2006 21:38:04 -0700, Unknown W. Brackets wrote:
>
>
>>Walter,
>>
>>My most common use for having this is simple...
>
>
> Excellent reply and I'm now convinced too.
>
> As a heretical aside, with the almost released new version of Build, you
> can do something like the C-styled assert macro.
>
> You can define a macro replacement pattern such as ...
>
> regexp <:assert\s(.*)::(.*):> =
> if (!($1)) {writefln(`%%s:%%s`, `$1`, `$2`); assert(0);}
>
> and then write in your code ...
>
> <:assert result != 0::Bad result:>
>
> which will transform into ...
>
> if (!(result != 0)) {writefln(`%s:%s`, `result != 0`, `Bad result`); assert(0);}
>
I wish I could understand why this is needed in Build, Derek ... Build is truly great, at what it does well. Now it apparently allows one to intimately tie their code to Build, for all eternity, by extending the D language? Does this new stuff slow it down even a tiny bit?
Sorry if this comes off a bit negative, but Build is just so good as it is. Still, it is your baby :)
|
June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to kris | On Wed, 31 May 2006 23:12:42 -0700, kris wrote: > I wish I could understand why this is needed in Build, Derek ... Build is truly great, at what it does well. Now it apparently allows one to intimately tie their code to Build, for all eternity, by extending the D language? Does this new stuff slow it down even a tiny bit? > > Sorry if this comes off a bit negative, but Build is just so good as it is. Still, it is your baby :) Not at all! I love to hear real users' feedback. Rest assured though that from a performance point of view, you won't notice anything if you aren't using this facility, because it doesn't do text preprocessing on ".d" files. Instead you have to explicitly use ".mac" files which are transformed into ".d" files. However in the end, you are not forced into using the text processing stuff, just like you are not forced into using 'goto'. One reason for extending Build is so I can use it to build things other than D applications. But I've kept in mind the 'normal' case of using it with D so that is where the performance bias is. But there will now be a few milliseconds extra delay at start up time because I've replaced a lot of hard-coded strings with user-definable ones, which are cached when the program starts. ------ I just had a bit more of a go at an 'assert' macro and it can actually do this ... regexp assert\((.*),(.*)\); = if (!($1)) {writefln(`%%s:%%s`, `$1`, $2); assert(0);} used as ... assert(result != 0, "Bad result"); and comes out as ... if (!(result != 0)) {writefln(`%s:%s`, `result != 0`, "Bad result"); assert(0);} So Walter, if you want to stop this nasty abomination of source code abuse, please allow coder defined messages in the built-in assert statement ;-) -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 1/06/2006 4:20:39 PM |
June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to Brad Roberts | On Wed, 31 May 2006, Brad Roberts wrote: > On Wed, 31 May 2006, Walter Bright wrote: > > > braddr@puremagic.com wrote: > > > I have been toying with D to bring myself up to speed and I found myself > > > writing > > > a lot of unit tests, always a good thing. In those unit tests I found > > > myself > > > writing a lot of blocks like: > > > > > > if (cond) > > > { > > > writefln("some debugging output to make my life easier"); > > > assert(false); > > > } > > > > > > I know many don't like unit tests to have output, but I do. > > > > Why not: > > > > assert(!cond); // some debugging output to make my life easier > > > > ? You'll need to go look at the source anyway when the assert trips, so what advantage is there to print the comment? > > I've reapplied the referenced patch to dmd/gdc and it works when used properly. However, exactly like it was before, it's got a number of bugs when used improperly. I need to learn more about dmd and gdc both to fix the thing to be robust enough to actually merge in. The current patch: http://www.puremagic.com/~braddr/d/assert-optional-message-0.2-gdc-0.18.diff http://www.puremagic.com/~braddr/d/assert-test.d There's a couple issues with the code as it stands: 1) most of the code is in the gdc layer, meaning that to incorporate with dmd walter will have to do some work. This can't be helped, probably. 2) rather than introduce a new _d_assert_with_message() api to the runtime, I've chosen to default to "" if no assert message is specified. 3) the runtime code in phobos/std/assertinternal.d recognizes "" as 'no message' 4) assert(condition, non-string-constant) produces an ICE in the gdc glue layer 5) assert(condition, non-string-expression) produces an odd error message: Integer constant expression expected instead of (test7func)() I'm continuing to work on 4 and 5. For now, I'm leaving 1-3 as is unless there's some outcry that guilts me into working on them more. Later, Brad |
June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Derek Parnell wrote: > Rest assured though that from a performance point of view, you won't notice > anything if you aren't using this facility, because it doesn't do text > preprocessing on ".d" files. Instead you have to explicitly use ".mac" > files which are transformed into ".d" files. Whew! Thanks :-D [snip] > So Walter, if you want to stop this nasty abomination of source code abuse, > please allow coder defined messages in the built-in assert statement ;-) Right on! |
June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Derek Parnell wrote: > On Wed, 31 May 2006 23:12:42 -0700, kris wrote: > > [snip] > > So Walter, if you want to stop this nasty abomination of source code abuse, please allow coder defined messages in the built-in assert statement ;-) > "Alright, this is a hold up! No body move! "Now, listen up; in this bag here I 'ave a three megaton regex macro pre-processor, and I ain't afraids to use it! If youse don't comply wit my demands, you'll leave me no choice but to butcher your pristine littl' language just like wot happened to C! "First, make it so that we can prints us some bloody context from asserts! "Second, we wants to bloody know where in a file the bloody exceptions are commin' from, and no not everyone can figure out how to use bloody WinDbg! "Thirds, I wants me a bloody sandwich!" "This is the police! We have the newsgroups surrounded; come out with your hands up, and the new version of build clearly visible or we'll shoot you!" "Oh 'ell." -------------------- On a more serious note, this looks *evil*. In a, y'know, really handy kind of a way. But what I've always wanted is something similar to what Nemerle has. For example, this is how the 'for' structure is defined in Nemerle: # macro for (init, cond, change, body) # { # <[ # $init; # def loop () : void { # if ($cond) { $body; $change; loop() } # else () # }; # loop () # ]> # } Everything inside the <[ ... ]> "quotes" is treated as the substitute syntax tree. The nice thing about this over plain old text substitution is that it's all typesafe: it only allows you to substitute complete, valid syntax trees. Aside from that, you can also directly create and modify the AST (since the "macro" is really just a function run by the compiler; the funky <[ ... ]> quotes are just syntactic sugar). Whatever you return from the function is what replaces the macro use in the source file. Anyway, just my AU$0.02. -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/ |
June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | In article <2dpe83lsz5rb.v7hpd58hsxeu.dlg@40tude.net>, Derek Parnell says... > >One reason for extending Build is so I can use it to build things other than D applications. But I've kept in mind the 'normal' case of using it with D so that is where the performance bias is. Its interesting that you mention this. I recently drafted a parser-frontend generator that generates .d code as output; it works a treat, but I'm presently having to go through multiple build steps. So, would "things other than D applications" happen to cover preprocessors other than just .mac file handling? ;) >So Walter, if you want to stop this nasty abomination of source code abuse, please allow coder defined messages in the built-in assert statement ;-) Nice. In a more serious, and on-topic note, I too believe that assert() could stand some expansion to allow for more succinct error reporting. It all comes down to the matter of reporting "how and why" something breaks rather than just "where". As a preface, I for one do not use an IDE when developing my software. D seems to do pretty well for me without it, although I'm still longing for out-of-the-box stack tracing. Anyway, so I run some code that trips on an assert, and it coughs up "foobar.d(42)" as where I need to look. The assert has done its job, as I go to line #42 and go hunting for the reason behind why it tripped up. As I'm basically flying blind (no watch window and no stack trace), my next step is almost always: add a writefln() before the assert to get some more information as to how this happened. Meshing those two steps seems like an obvious choice to me. Another way to look at it is in the use of static assert(). With the compile-time regexp processor(s) out there, they halt on static assert() and then cough up some rudimentary explaination as to *why* using pragma(msg). I wouldn't even consider either implementation usable without the msg/assert idiom, so I don't really use them apart from each other. In fact, I'll argue that its impossible to meaningfully extend the compiler/D-grammar through templates without using the two together; the library user just wouldn't have a clue otherwise. To sum up: I honestly feel that the two capabilities, assert() and writefln(), should be merged into an extended assert() statment, for the sake of encouraging better coding and library use. - EricAnderton at yahoo |
June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to pragma | pragma wrote:
> In a more serious, and on-topic note, I too believe that assert() could stand
> some expansion to allow for more succinct error reporting. It all comes down to
> the matter of reporting "how and why" something breaks rather than just "where".
>
> As a preface, I for one do not use an IDE when developing my software. D seems
> to do pretty well for me without it, although I'm still longing for
> out-of-the-box stack tracing.
>
> Anyway, so I run some code that trips on an assert, and it coughs up
> "foobar.d(42)" as where I need to look. The assert has done its job, as I go to
> line #42 and go hunting for the reason behind why it tripped up. As I'm
> basically flying blind (no watch window and no stack trace), my next step is
> almost always: add a writefln() before the assert to get some more information
> as to how this happened. Meshing those two steps seems like an obvious choice
> to me.
What I do is redefine the implementation of assert to do:
*(cast(int *)0) = 0;
That way, I get a segmentation fault and a core dump that the debugger (gdb) is able to use to present me with a back trace and (all) local variables available for inspection. This is immensely more useful than letting assert throw an exception, which means losing all state and stack trace information.
/Oskar
|
June 01, 2006 stack tracing {was assert(condition[, message]) patch} | ||||
---|---|---|---|---|
| ||||
Posted in reply to Oskar Linde | Oskar Linde wrote:
> pragma wrote:
>> Anyway, so I run some code that trips on an assert, and it coughs up
>> "foobar.d(42)" as where I need to look. The assert has done its job, as I go to
>> line #42 and go hunting for the reason behind why it tripped up. As I'm
>> basically flying blind (no watch window and no stack trace), my next step is
>> almost always: add a writefln() before the assert to get some more information
>> as to how this happened. Meshing those two steps seems like an obvious choice
>> to me.
>
>
> What I do is redefine the implementation of assert to do:
>
> *(cast(int *)0) = 0;
>
> That way, I get a segmentation fault and a core dump that the debugger (gdb) is able to use to present me with a back trace and (all) local variables available for inspection. This is immensely more useful than letting assert throw an exception, which means losing all state and stack trace information.
>
> /Oskar
And therein lies the key: what everyone is asking for is a means to capture additional state with the assert()
Ideally, all code-testing would be performed within the comforting arms of a debugger. But it doesn't happen that way and, due to Murphy's law, the one and only time your code trips up is when it's not in the debugger. That's when you need additional state to help track things down; especially with those "non repeatable" bugs.
Having said that, a very large part of the valuable state is the stack-trace ~ "how did we get here" can be just as important as some key variable. Often more so. Thus, I tend to look at assert as the bare minimum of tools; scraping the barrel, if you will. That goes to show how poor the runtime diagnostic support really is in D at this time ~ we're actually better off with printf() than most anythng else :)
Thus when all is said and done, having support for a stack-trace seems far more valuable than the 'convenience' of an assert message. Although in the absence of the former, it's easy to see why assert() gets so much attention.
Finally, I suspect adding printf formatting to assert() would be binding complexity at a delicate level; partly because the formatting might try to allocate memory?
Let's get stack-tracing supported, instead of depending upon the marginally useful assert() statement :D
- Kris
|
June 01, 2006 Re: assert(condition[, message]) patch | ||||
---|---|---|---|---|
| ||||
Posted in reply to pragma | pragma wrote:
>
> Another way to look at it is in the use of static assert(). With the
> compile-time regexp processor(s) out there, they halt on static assert() and
> then cough up some rudimentary explaination as to *why* using pragma(msg). I
> wouldn't even consider either implementation usable without the msg/assert
> idiom, so I don't really use them apart from each other. In fact, I'll argue
> that its impossible to meaningfully extend the compiler/D-grammar through
> templates without using the two together; the library user just wouldn't have a
> clue otherwise.
Good point. If this change were made, would it apply to static assert as well? It would certainly be nice.
Sean
|
Copyright © 1999-2021 by the D Language Foundation