Its been a looooong night.
If anyone didn't already see me make an ass out of myself about
C<while(1) { foo() } sub foo { last }> on p5p, this was all sparked
when japhy posted on FWP code that used that little "feature". Since
then I'd gotten it into my head that there must be some way to detect
that without actually running the code.
Well, now there is. And a bunch of other things. B::Scan (the name
will be changing). All using B, so its difficult to trick. Here's an
example...
$ perl -MO=Scan /usr/local/lib/perl5/5.6.1/AutoLoader.pm
package AutoLoader has an AutoLoader!
Symbol Exporter::ExportLevel referenced from AutoLoader
at /usr/local/lib/perl5/5.6.1/AutoLoader.pm line 121
Symbol Exporter::import referenced from AutoLoader
at /usr/local/lib/perl5/5.6.1/AutoLoader.pm line 122
eval STRING detected
at /usr/local/lib/perl5/5.6.1/AutoLoader.pm line 158
/usr/local/lib/perl5/5.6.1/AutoLoader.pm syntax OK
It detects things like Autoloaders, eval STRING, goto LABEL, dynamic
method calls, using non-exported variables and functions...
This is just a proof of concept, but it proves a few things...
- B isn't impossible to learn. This took me about 10 hours
of straight deep hacking and stealing code from B::Deparse and
B::Fathom. But its all so clear now...
- We can scan Perl for questionable constructs to >80%
reliability.
>From there I can now assert with confidence...
- CPANTS is definately doable.
- An automated Perl refactoring tool is possible.
CPANTS needs a way to find pathological and inconsistent constructs
via lexical scanning. This does that (although different constructs).
A Perl refactoring tool first needs to find the cases it cannot handle
and warn the user to check them by hand. That's basically what this
code does. Furthermore, I now know how to find method calls,
variables and subroutine declarations, what file they're in and what
line its on. From there its a relatively "solved" problem to modify
the code.
Just to be sure this thing really works, here's a fairly pathological
case... Damian's code! ;)
$ perl -MO=Scan /usr/local/lib/site_perl/Text/Balanced.pm
package Text::Balanced has an AutoLoader!
Symbol Exporter::export_ok_tags referenced from Text::Balanced
at /usr/local/lib/site_perl/Text/Balanced.pm line 31
eval STRING detected
at /usr/local/lib/perl5/5.6.1/SelfLoader.pm line 36
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 316
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 324
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 336
eval STRING detected
at /usr/local/lib/site_perl/Text/Balanced.pm line 341
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 356
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 365
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 367
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 375
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 378
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 386
goto LABEL or EXPR
at /usr/local/lib/site_perl/Text/Balanced.pm line 387
/usr/local/lib/site_perl/Text/Balanced.pm syntax OK
The current implementation works, but its a mess. Just a
proof-of-concept. It needs a better name. I'm not putting it on
CPAN. You can get it from:
http://www.pobox.com/~schwern/src/B-Scan-0.01.tar.gz
It needs UNIVERSAL::exports (available from CPAN) and perl5.6.0. It
might work on 5.005_03, dunno. I had to dig into some undocumented
things in B.
--
Michael G. Schwern <[EMAIL PROTECTED]> http://www.pobox.com/~schwern/
Perl6 Quality Assurance <[EMAIL PROTECTED]> Kwalitee Is Job One
AY! The ground beef, she is burning my groin!
http://sluggy.com/d/990105.html