
perlbug-comment at perl
May 3, 2012, 10:47 PM
Views: 76
Permalink
|
|
[perl #107004] require parses barewords strangely
|
|
On Sun Dec 25 14:20:49 2011, sprout wrote: > When require is followed by a bareword, if that bareword is followed > by an operator that has higher precedence than require, it falls back > to treating its argument as a normal expression, but not quite. > > Here is the special behaviour: > > $ perl5.15.5 -MO=Concise -e 'require a::b' > 5 <@> leave[1 ref] vKP/REFC ->(end) > 1 <0> enter ->2 > 2 <;> nextstate(main 1 -e:1) v:{ ->3 > 4 <1> require sK/1 ->5 > 3 <$> const[PV "a/b.pm"] s/BARE ->4 > -e syntax OK > > Notice the "a/b.pm". > > Now if we put ‘. 1’ after it (+1 doesn’t work, because of bug > #105924): > > $ perl5.15.5 -MO=Concise -we 'require a::b . 1' > 7 <@> leave[1 ref] vKP/REFC ->(end) > 1 <0> enter ->2 > 2 <;> nextstate(main 1 -e:1) v:{ ->3 > 6 <1> require sK/1 ->7 > 5 <2> concat[t1] sK/2 ->6 > 3 <$> const[PV "a::b"] s/BARE ->4 > 4 <$> const[IV 1] s ->5 > -e syntax OK > > That I can understand, as a::b is a string in the absence of any other > interpretation, ‘a::b . 1’ being the argument to require, which is > more than a single bareword. > > But if there is a subroutine named a::b, things get strange: > > $ perl5.15.5 -MO=Concise -we 'sub a::b; require a::b . 1' > 7 <@> leave[1 ref] vKP/REFC ->(end) > 1 <0> enter ->2 > 2 <;> nextstate(main 1 -e:1) v:{ ->3 > 6 <1> require sK/1 ->7 > 5 <2> concat[t1] sK/2 ->6 > 3 <$> const[PV "a::b"] s/BARE ->4 > 4 <$> const[IV 1] s ->5 > -e syntax OK > > The a::b should be a subroutine call. When ‘require’ is followed by a bareword, it is treated specially in three different ways: 1. The token following it is forced to be a bareword, even if there is a subroutine with that name, and even under strict mode. 2. The bareword has its double colons changed to slashes and has .pm appended to the end. 3. A stash is autovivified during compilation. Items 1 and 3 happen in the tokeniser, based on whether the token that immediately follows the ‘require’ token is an identifier. Item 2 happens in op.c when the op tree is being built, and depends on whether the child op is a single constant that was a bareword. This means that cases like ‘require a::b . "foo"’ treat a::b as a bareword, exempt from strict mode, but that bareword does not undergo the s|::|/|g and .= ".pm" treatment. So the bareword is only half special. (This also means that ‘require foo’ is allowed under strict, but ‘require(foo)’ isn’t, even though the latter, when used outside of strict mode, turns into ‘require "foo.pm"’. However, ‘require(foo)’ treats foo as a sub call if there is a foo sub in scope. I don’t want to deal with that just yet.) I’m wondering whether it would be possible to make the require code in toke.c scan past the bareword and see whether it is followed by something that would make the child op of require into something more than just a bareword; i.e., an infix op of higher precedence than require (<< >> and above) or an opening parenthesis (for require foo()). If such a character is *not* found, then the bareword can get its special treatment via S_force_word, etc. Can anyone see anything I’ve missed? Simply moving all the bareword handling to op.c won’t work, because ‘require foo’ will turn into ‘require(foo())’ if there is a foo sub. Though it’s usually possible to detect that, it isn’t with constant subs. -- Father Chrysostomos
|