Re: Why no bareword warnings while inside of BEGIN (more)
by tye (Sage) on Mar 22, 2004 at 23:20 UTC
|
It appears that the test for barewords happens after compiling is finished. The test for undeclared variables also appears to wait until compilation is finished but happens sooner:
> perl -w
use strict;
BEGIN {
while( calldepth < 5 ) {
sleep 1;
}
print $n;
}
Global symbol "$n" requires explicit package name at - line 6.
BEGIN not safe after errors--compilation aborted at - line 7.
Note that I don't even have to type end-of-file there but that the error didn't appear until I finished the BEGIN block. If the infinite loop ever finished, then you'd get the 'bareword' error:
> perl -w
use strict;
BEGIN {
my $n= 5;
while( calldepth < $n ) {
warn $n--;
}
}
Argument "calldepth" isn't numeric in numeric lt (<) at - line 4.
5 at - line 5.
4 at - line 5.
3 at - line 5.
2 at - line 5.
1 at - line 5.
my $x
= 5;
BEGIN {
warn "interesting"
}
Bareword "calldepth" not allowed while "strict subs" in use at - line
+4.
BEGIN not safe after errors--compilation aborted at - line 12.
Note that I still didn't have to type end-of-file. And it didn't take until the file was finished being compiled. So it seems like this might be a problem that can be fixed. The BEGIN block can't be run until it is done being compiled. The check for barewords is happening after the block is done being compiled but after the block is run.
So the next step is to figure out why it waits (until a subsequent BEGIN block is declared, in the above example) before the check for barewords is done?
Updated.
| [reply] [d/l] [select] |
|
The code to execute BEGIN immediately doesn't properly check the compilation error flag before executing the block. Here's a patch against 5.8.3:
--- op.c.orig 2004-03-22 16:59:09.000000000 -0800
+++ op.c 2004-03-22 16:59:25.000000000 -0800
@@ -4359,7 +4359,7 @@
if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I')
goto done;
- if (strEQ(s, "BEGIN")) {
+ if (strEQ(s, "BEGIN") && !PL_error_count) {
I32 oldscope = PL_scopestack_ix;
ENTER;
SAVECOPFILE(&PL_compiling);
It already appears to be fixed in 5.9.1. | [reply] [d/l] |
Re: Why no bareword warnings while inside of BEGIN
by Limbic~Region (Chancellor) on Mar 22, 2004 at 22:57 UTC
|
JayBonci,
If you want to see it blow up you will have to do:
BEGIN {
while( calldepth < 5 ) {
last;
}
}
From perldoc perlmod
A BEGIN subroutine is executed as soon as possible, that is, the moment it is completely defined, even before the rest of the containing file is parsed.
You have put it into an infinite loop - never giving it a chance to throw the error.
Cheers - L~R | [reply] [d/l] |
|
The BEGIN block *can't* be run until the block is finished being compiled. If the block is finished being compiled, it is reasonable to expect that barewords would have been detected. As I show elsewhere, other types of 'strict' errors are handled correctly here.
So I don't see how your reading of the documentation explains this problem away. The quoted section says that it runs before the "rest of the containing file is parsed". The error is in the code being run. It certainly can and should report fatal errors in that code before it runs it.
| [reply] |
|
tye,
So this is a bug/feature, I see it in your reply below.
I thought:
Because a BEGIN block executes immediately,...
Meant that it executed and then execeptions were thrown. After running it through perl -MO=Deparse, I thought it was expected behavior since it doesn't seem to matter what kind of loop it is - the error isn't thrown until after it is completed.
Cheers - L~R
Update: Changed bug/feature to statement rather than question after seeing tye's reply further down in thread
| [reply] |
Re: Why no bareword warnings while inside of BEGIN
by ChemBoy (Priest) on Mar 22, 2004 at 22:54 UTC
|
I don't know the answer, but I suspect it has to do with the "run-as-soon-as-possible" nature of BEGIN blocks. One reason I suspect this is that if you change calldepth < 5 to calldepth > 5, you get a bareword error. Also, you get a bareword error (or at least, I do) if you run a similar one-liner:
perl -e 'use strict;BEGIN{if (bareword > 1) {1} }'
which probably makes the answer obvious to some people, though it doesn't to me. :-)
If God had meant us to fly, he would *never* have given us the railroads. --Michael Flanders
| [reply] [d/l] |
|
Okay, so a pared down example of why this is kinda scarry is this:
perl -e "use strict; BEGIN { while(bareword < 1) {1} }"
Cycles forever. No error
perl -e "use strict; BEGIN { while(bareword > 1) {1} }"
Throws the bareword error
...wierd.
--jay
| [reply] [d/l] [select] |
|
JayBonci,
See my post below. The while loop is infinite because 0 < 1. It never enters the loop when 0 > 1. Not throwing the error until after the code is run may or may not be expected behavior as tye points out.
Cheers - L~R
| [reply] |
Re: Why no bareword warnings while inside of BEGIN
by muba (Priest) on Mar 22, 2004 at 22:41 UTC
|
update: nevermind
Just know that a BEGIN block is not marked by a sub keyword. You just use BEGIN {...}
Also, IIRC, the strict and warning pragma's are imported *after* the BEGIN block. But it's very good possible I'm wrong here.
| [reply] [d/l] |
|
$ perl
use strict;
BEGIN { $x = 'y'; $$x = 1; print $y }
Global symbol "$x" requires explicit package name at - line 2.
Global symbol "$x" requires explicit package name at - line 2.
Global symbol "$y" requires explicit package name at - line 2.
BEGIN not safe after errors--compilation aborted at - line 2.
As it turns out, use calls reduce to BEGIN blocks and BEGIN blocks fire in order of encountering. | [reply] [d/l] [select] |
|
A BEGIN block is not marked by the sub keyword.
Instead, you just use BEGIN {...}
It can be, though. "sub BEGIN" doesn't create a normal sub called BEGIN, but it is valid syntax. In fact, it is how B::Deparse deparses BEGIN blocks. The same goes for CHECK, INIT and END. See also what perlmod has to say about this.
| [reply] |
require strict?
by Anonymous Monk on Mar 22, 2004 at 23:08 UTC
|
what do you mean require strict?
That's no good | [reply] |