On Sun, Jan 13, 2008 at 11:22:44PM -0600, Patrick R. Michaud wrote: : On Sun, Jan 13, 2008 at 11:35:17PM +0100, Cosimo Streppone wrote: : > - Is [1] the correct way of declaring "todo" tests? : > What's the equivalent in new compiler directives : > of `:todo<feature>', `:todo<bug>', and ':todo'? : > [1] t/spec/S29-str/quotemeta.t : : Larry, Jerry, and I discussed this a couple of weeks ago : and here's my vision for how it should work. To simplify : things, let's break it into two parts: (1) how to mark tests : as 'todo', and (2) how to do this for specific implementations.
I've just checked in a "util/fudge" preproprocessor into the pugs repo that approximates what we've been talking about, or at least my version of it. :) There are a few differences though, mostly lifted restrictions. You can use the #?foo: bar 'reason' notation on either blocks or statements, and you don't generally have to worry about the count, and when you do, you put it in front of the verb instead of as one of the arguments. : For the first part, we identify a test function that looks like : : sub todo($reason, $count=1) { ... } : : Calling C<< todo('foo', 3); >> says that the next three tests are : to be marked as TODO with 'foo' given as a reason. Unfortunately, the pugs Test::todo function doesn't take a count there, but it's not needed in the preprocessor approach. You can just put the repeat count before the verb: #?pugs: 3 todo 'foo' and the preprocessor automatically applies it to the next 3 tests. You can also say #?pugs: 999 todo 'foo' is(...); is(...); is(...); #?pugs: 0 if you don't want to count them, and the 0 overrides whatever is left of the 999. If you use the block form, it automatically scans the block for the number of tests, so you can also say: #?rakudo: skip 'unimpl' #?smop: eval 'parsefail' #?pugs: todo 'foo' { is(...); is(...); is(...); } and it automatically installs the correct skip count where needed. : Secondly, to indicate that a function should be invoked only : in specific compiler implementations, we propose a compiler or : preprocessor syntax that looks like: : : #?perl6: fn(args); : : The "perl6" compiler will treat this as a valid function call, : all other implementations will view the line as a comment. The semicolon isn't really needed there. Also, depending on the verb, the argument may end up getting fed to the skip() instead, and the verb applied to the block. : This is not yet intended to be the required behavior for all : compiler implementations -- it's just the approach that Perl 6 : on Parrot will be using for now. We'll try it and see how : it works. The available verbs are: #?foo: todo(reason) #?foo: skip(reason) #?foo: eval(reason) #?foo: try(reason) Any of these may be applied to either a block or a statement. : To return to the example given: : : #?pugs: todo('Test Config.pm availability', 1); : is('Config.pm', 'available', 'Config.pm availability'); That's now just simply #?pugs: todo 'Test Config.pm availability' is('Config.pm', 'available', 'Config.pm availability'); The preprocessor rewrites it to todo('Test Config.pm availability'); is('Config.pm', 'available', 'Config.pm availability'); : This looks good to me -- this says that the Config.pm : test is being marked as todo only for Pugs (if Pugs chooses : to implement this behavior). Compilers other than Pugs : will simply see the #?pugs: line as a normal comment, and : therefore will not treat the test as being 'todo'. : : We also have a syntax for handling 'skip' blocks and text. : For perl6 on Parrot, the syntax will be: : : #?perl6: skip('Foo', 3); #SKIPBLOCK : { : isnt('foo', 'bar', 'foo is not bar'); : isnt('bar', 'foo', 'bar is not foo'); : is('foo', 'bar', 'foo is bar'); : } : : The presence of #SKIPBLOCK at the end of a #?perl6 line means to : generate "skip" results for the next three tests, and to skip over : the next brace-delimited "block". The braces must be at the : beginning of source lines. Anything between the braces is : ignored by the compiler at runtime, either because it skips : over the "block" or because a preprocessor has stripped it : somehow. Now you just write: #?rakudo: skip 'Foo' { isnt('foo', 'bar', 'foo is not bar'); isnt('bar', 'foo', 'bar is not foo'); is('foo', 'bar', 'foo is bar'); } and it automatically turns into something like skip(3,'Foo'); # { # isnt('foo', 'bar', 'foo is not bar'); # isnt('bar', 'foo', 'bar is not foo'); # is('foo', 'bar', 'foo is bar'); # } Whereas #?rakudo: todo 'Foo' turns it into: { todo('Foo'); isnt('foo', 'bar', 'foo is not bar'); todo('Foo'); isnt('bar', 'foo', 'bar is not foo'); todo('Foo'); is('foo', 'bar', 'foo is bar'); } and #?rakudo: eval 'Foo' turns it into: eval('{ isnt(\'foo\', \'bar\', \'foo is not bar\'); isnt(\'bar\', \'foo\', \'bar is not foo\'); is(\'foo\', \'bar\', \'foo is bar\'); }') // skip(3, 'Foo'); and #?rakudo: try 'Foo' turns it into: try({ isnt('foo', 'bar', 'foo is not bar'); isnt('bar', 'foo', 'bar is not foo'); is('foo', 'bar', 'foo is bar'); }) // fail('Foo'); (which doesn't attempt to keep the test numbers in sync, but that gets caught by the number of planned tests anyway). Larry