On Wed, Jul 08, 2009 at 10:03:38AM +0200, Vincent Pit wrote: > > > Maybe this optimisation : > > > > [rafael@scipion ~]$ perl5.10.0 -MO=Deparse -e 'if(not $a or not $b){}' > > if (not $a or not $b) { > > (); > > } > > -e syntax OK > > [rafael@scipion ~]$ bleadperl -MO=Deparse -e 'if(not $a or not $b){}' > > unless ($a and $b) { > > (); > > } > > -e syntax OK > > > > Which seems to come from : > > > > commit edbe35ea95baf286c38bf4d7db7d18b82ecce254 > > Author: Vincent Pit <perl@profvince.com> > > Date: Sat Aug 30 00:47:28 2008 +0200 > > > > Re: unless(...) terser than if(!...) > > Message-ID: <48B86060.4090905@profvince.com> > > > > p4raw-id: //depot/perl@34310 > > > > Not sure Deparse will be able to cope with this. > > This is highly possible. > > If by cope you mean "being able to recreeate the precise original > code", then I don't think so either. Here's a start at the impossible: ====================================================================== --- lib/B/Deparse.pm.org 2009-08-07 20:30:49.000000000 +0200 +++ lib/B/Deparse.pm 2009-08-08 20:16:08.000000000 +0200 @@ -2231,6 +2231,8 @@ return "$blockname ($left) {\n\t$right\n\b}\cK"; } elsif ($cx < 1 and $blockname and not $self->{'parens'} and $self->{'expand'} < 7) { # $b if $a + $blockname = ($blockname eq "if" ? "unless" : "if") . " not" + if $left->name eq "null" and B::ppname($left->targ) eq "pp_not"; $right = $self->deparse($right, 1); $left = $self->deparse($left, 1); return "$right $blockname $left"; ====================================================================== Before the patch: $ ./perl -MO=Deparse -e 'die if not $a' die unless $a; -e syntax OK After the patch: $ ./perl -Ilib -MO=Deparse -e 'die if not $a' die if not $a; -e syntax OK This is by no means a complete solution. In fact I'm not even convinced that a full solution is possible. But it is heading in the direction of an improvement and, as such, it may merit further investigation. There are at least the following problems: 1. You can't just stick a "not" in there and expect it to work. You probably have to de De Morgan (to Morgan?) the condition. 2. "not" and ! are different. 3. Something similar needs to be done for "if (not $a) { die }" This is probably a reasonably simple task for someone familiar with the optree, but it might also be a nice introduction for someone who would like to become more familiar with it. No C is required. Any volunteers? > But it also can't tell the > difference between "1 if $x" and "$x and 1", or recover optimized out > sections, so that shouldn't be a blocker. My opinion is that it is nice if Deparse can get as close as possible to to the original code but if it can't tell that certain optimisations have been made then it's not the end of the world. I expect (and hope for) this to happen more and more as we are able to optimise the optree, possibly with the optimisations being controlled by a switch, if they are expensive. Having said that, it would be nice if there were a way to be able to faithfully recreate the original source code. This could be of great benefit to source code analysis tools. What options do we have? 1. B::Deparse - not always accurate 2. Go through the debugger - line based - slow 3. MAD - no one has this compiled in 4. Use the cop line and file data to go back to the original file - line based - file may not be there - if it is, it might be hard to find (file is relative to the cwd when it was opened) - only available for cops 5. Anything else? What have I missed? Is this important? Is effort better directed somewhere else? Do we have a champion? I'm CCing Gerard Goossen since I wonder whether his proposal "Changing the Perl 5 optree build process into a Abstract Syntax Tree generation and a code generation step" might be able to provide any benefits in this area. Or perhaps it might make things more difficult? -- Paul Johnson - paul@pjcj.net http://www.pjcj.netThread Previous | Thread Next