develooper Front page | perl.perl5.porters | Postings from May 2012

[perl #107004] require parses barewords strangely

Thread Next
From:
Father Chrysostomos via RT
Date:
May 3, 2012 22:47
Subject:
[perl #107004] require parses barewords strangely
Message ID:
rt-3.6.HEAD-4610-1336110456-1615.107004-14-0@perl.org
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


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About