Quick notes when hacking for compile time
作者:gugod 發佈於:Following my previous post (Running in the compile time), it'll be very helpful if you know what's going to try next when it doesn't work as expected.
Here are some notes that I concluded and found to be helpful:
import
is executed in compile timeperl -MO=Deparse
is your friendperl -MO=Concise
tooDevel::Declare::toke_skipspace
helps peaking the next line of codelineseq
op gives you a chance to see every lines of code when it is compiling- Search ~flora for goodies
import
is executed in compile time
This is only true when the module is included with use
, but not reuquire
. Since use Foo
is the same as saying:
BEGIN {
require Foo;
Foo->import;
}
This means that B::Hooks::Parser::get_linestr
and friends are all useful in import
.
perl -MO=Deparse
is your friend
It prints the code again in a form that perl
understands it, and it helps you understand how perl
interprets your code. For a simple example:
> perl -MO=Deparse -e 'print 42'
print 42;
-e syntax OK
Notice that the semi-colon is added. For a weird example:
> perl -MO=Deparse -e 'print 42; 42'
print 42;
'???';
-e syntax OK
Perl thinks that latter 42 is just the same as string '???'. That's true, because constants evaluated void context can be simply discard because it's not used anywhere else. However, see this:
> perl -MO=Deparse -e 'sub { print 42; 42 }'
sub {
print 42;
42;
}
;
-e syntax OK
If the same code lives in a sub {}
, the later 42 is then meaningful because that's the return value of the sub.
I also use this tool to write a JAPH, see here and here.
perl -MO=Concise
too
This is harder to read but quite useful sometimes. It gives you the syntax tree of your code:
> perl -MO=Concise -e 'sub { print 42; 42 }'
6 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v:{ ->3
5 <1> refgen vK/1 ->6
- <1> ex-list lKRM ->5
3 <0> pushmark sRM ->4
4 <$> anoncode[CV ] lRM ->5
-e syntax OK
Each line represents a node, which is always an OP
of different type. You can read the name of them there: leave, enter, nexstate, refgen ... The number in the beginning and the end is the execution order, which is not necessarily the same as the order of tree nodes because the evaluation of expressions of leave nodes usually happens first.
Devel::Declare::toke_skipspace
helps peaking the next line of code
I suggest reading the documentation of Devel::Declare for understanding how it works. Also the t/
directory of it, lots of gems in there.
lineseq
op gives you a chance to see every lines of code when it is compiling
Well, almost. I wrote a example program that prints the body when it compiles.
You'll have to use the value of $offset
to know the currently parsed position in the $line
.
Search ~flora for goodies
Yes yes yes.