Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Perl: porters
[perl #107004] require parses barewords strangely
 

Index | Next | Previous | View Flat


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

Subject User Time
[perl #107004] require parses barewords strangely perlbug-comment at perl May 3, 2012, 10:47 PM
    [perl #107004] require parses barewords strangely perlbug-comment at perl May 4, 2012, 5:01 PM
    [perl #107004] require parses barewords strangely perlbug-comment at perl May 10, 2012, 6:38 PM

  Index | Next | Previous | View Flat
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.