This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
make qr/(?{})/ behave with closures
authorDavid Mitchell <davem@iabyn.com>
Wed, 12 Oct 2011 13:01:50 +0000 (14:01 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 13 Jun 2012 12:25:50 +0000 (13:25 +0100)
commitd63c20f27b4a88c274844b2b635deb3c6588cccd
tree419e8d46117855aa07627636841d9a7208f0320e
parent2866decb530d50f622ad6853fed7f30562e474ce
make qr/(?{})/ behave with closures

With this commit, qr// with a literal (compile-time) code block
will Do the Right Thing as regards closures and the scope of lexical vars;
in particular, the following now creates three regexes that match 1, 2
and 3:

    for my $i (0..2) {
        push @r, qr/^(??{$i})$/;
    }
    "1" =~ $r[1]; # matches

Previously, $i would be evaluated as undef in all 3 patterns.

This is achieved by wrapping the compilation of the pattern within a
new anonymous CV, which is then attached to the pattern. At run-time
pp_qr() clones the CV as well as copying the REGEXP; and when the code
block is executed, it does so using the pad of the cloned CV.
Which makes everything come out all right in the wash.

The CV is stored in a new field of the REGEXP, called qr_anoncv.

Note that run-time qr//s are still not fixed, e.g. qr/$foo(?{...})/;
nor is it yet fixed where the qr// is embedded within another pattern:
continuing with the code example from above,

    my $i = 99;
    "1"   =~ $r[1];    # bare qr:     matches: correct!
    "X99" =~ /X$r[1]/; # embedded qr: matches: whoops, it's still
       seeing the wrong $i
21 files changed:
dump.c
embed.fnc
embed.h
ext/Devel-Peek/t/Peek.t
op.c
op.h
perly.act
perly.h
perly.tab
perly.y
pp_hot.c
proto.h
regcomp.c
regcomp.h
regexec.c
regexp.h
t/lib/strict/subs
t/lib/strict/vars
t/re/pat_re_eval.t
t/re/re_tests
toke.c