Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interpolation of @{^CAPTURE} and its friends doesn't work #16050

Closed
p5pRT opened this issue Jun 27, 2017 · 21 comments
Closed

Interpolation of @{^CAPTURE} and its friends doesn't work #16050

p5pRT opened this issue Jun 27, 2017 · 21 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 27, 2017

Migrated from rt.perl.org#131664 (status was 'resolved')

Searchable as RT131664$

@p5pRT
Copy link
Author

p5pRT commented Jun 27, 2017

From ishigaki@cpan.org

Created by ishigaki@cpan.org

Interpolation of newly introduced @​{^CAPTURE} and its friends doesn't work well.
See the following examples​:

$ perl -E '"a"=~/(.)/; say ${^CAPTURE}[0]; say "${^CAPTURE}[0]"'
a
[0]

$ perl -E '"a"=~/(.)/; say @​{^CAPTURE}; say "@​{^CAPTURE}"'
a
a

$ perl -E '"a"=~/(?<b>.)/; say ${^CAPTURE}{b}; say "${^CAPTURE}{b}"'
a
{b}

$ perl -E '"a"=~/(?<b>.)/; say %{^CAPTURE}; say "%{^CAPTURE}"'
ba
%{^CAPTURE}

$ perl -E '"a"=~/(?<b>.)/; say @​{^CAPTURE}{b}; say "@​{^CAPTURE}{b}"'
a
a{b}

$ perl -E '"a"=~/(?<b>.)/; say %{^CAPTURE}{b}; say "%{^CAPTURE}{b}"'
ba
%{^CAPTURE}{b}

$ perl -E '"a"=~/(?<b>.)/; say ${^CAPTURE_ALL}{b}; say "${^CAPTURE_ALL}{b}"'
a
{b}

$ perl -E '"a"=~/(?<b>.)/; say %{^CAPTURE_ALL}; say "%{^CAPTURE_ALL}"'
ba
%{^CAPTURE_ALL}

$ perl -E '"a"=~/(?<b>.)/; say @​{^CAPTURE_ALL}{b}; say "@​{^CAPTURE_ALL}{b}"'
a
{b}

$ perl -E '"a"=~/(?<b>.)/; say %{^CAPTURE_ALL}{b}; say "%{^CAPTURE_ALL}{b}"'
ba
%{^CAPTURE_ALL}{b}

Hope this helps.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.26.0:

Configured by ishigaki at Wed May 31 14:15:00 JST 2017.

Summary of my perl5 (revision 5 version 26 subversion 0) configuration:
   
  Platform:
    osname=linux
    osvers=3.16.0-4-amd64
    archname=x86_64-linux
    uname='linux charsbar.org 3.16.0-4-amd64 #1 smp debian 3.16.39-1 (2016-12-30) x86_64 gnulinux '
    config_args='-Dprefix=/home/ishigaki/.plenv/versions/5.26.0 -de -Dusedevel -A'eval:scriptdir=/home/ishigaki/.plenv/versions/5.26.0/bin''
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=undef
    usemultiplicity=undef
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='cc'
    ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2'
    optimize='-O2'
    cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='4.9.2'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='cc'
    ldflags =' -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
    libs=-lpthread -lnsl -ldb -ldl -lm -lcrypt -lutil -lc
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.19.so
    so=so
    useshrplib=false
    libperl=libperl.a
    gnulibc_version='2.19'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E'
    cccdlflags='-fPIC'
    lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'

Locally applied patches:
    Devel::PatchPerl 1.48


@INC for perl 5.26.0:
    /home/ishigaki/.plenv/versions/5.26.0/lib/perl5/site_perl/5.26.0/x86_64-linux
    /home/ishigaki/.plenv/versions/5.26.0/lib/perl5/site_perl/5.26.0
    /home/ishigaki/.plenv/versions/5.26.0/lib/perl5/5.26.0/x86_64-linux
    /home/ishigaki/.plenv/versions/5.26.0/lib/perl5/5.26.0


Environment for perl 5.26.0:
    HOME=/home/ishigaki
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/ishigaki/.plenv/versions/5.26.0/bin:/home/ishigaki/.plenv/libexec:/home/ishigaki/.plenv/plugins/perl-build/bin:/home/ishigaki/.rakudobrew/bin:/home/ishigaki/.rbenv/shims:/home/ishigaki/.rbenv/bin:/home/ishigaki/.plenv/shims:/home/ishigaki/.plenv/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jun 28, 2017

From @Abigail

On Tue, Jun 27, 2017 at 12​:48​:37AM -0700, Kenichi Ishigaki wrote​:

# New Ticket Created by Kenichi Ishigaki
# Please include the string​: [perl #131664]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=131664 >

This is a bug report for perl from ishigaki@​cpan.org,
generated with the help of perlbug 1.40 running under perl 5.26.0.

-----------------------------------------------------------------
[Please describe your issue here]
Interpolation of newly introduced @​{^CAPTURE} and its friends doesn't work well.
See the following examples​:

$ perl -E '"a"=~/(.)/; say ${^CAPTURE}[0]; say "${^CAPTURE}[0]"'
a
[0]

That has nothing to do with @​{^CAPTURE}, but how interpolation works​:

  $ perl -E '@​foo = qw [a b c]; say "${foo}[0]"'
  [0]
  $

Interpolation works this way on purpose, the braces around the name
of the variable are allowed so you can interpolate a variable followed
by something in brackets without it being an indexing operation.

There's an ugly workaround​:

  $ perl -E '"foo" =~ /(foo)/; say "${\${^CAPTURE}[0]}"'
  foo
  $

$ perl -E '"a"=~/(?<b>.)/; say %{^CAPTURE}; say "%{^CAPTURE}"'
ba
%{^CAPTURE}

Hashes don't interpolate in perl5.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Jun 28, 2017

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jun 28, 2017

From ishigaki@cpan.org

On Tue, 27 Jun 2017 23​:37​:14 -0700, abigail@​abigail.be wrote​:

On Tue, Jun 27, 2017 at 12​:48​:37AM -0700, Kenichi Ishigaki wrote​:

# New Ticket Created by Kenichi Ishigaki
# Please include the string​: [perl #131664]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=131664 >

This is a bug report for perl from ishigaki@​cpan.org,
generated with the help of perlbug 1.40 running under perl 5.26.0.

-----------------------------------------------------------------
[Please describe your issue here]
Interpolation of newly introduced @​{^CAPTURE} and its friends doesn't
work well.
See the following examples​:

$ perl -E '"a"=~/(.)/; say ${^CAPTURE}[0]; say "${^CAPTURE}[0]"'
a
[0]

That has nothing to do with @​{^CAPTURE}, but how interpolation works​:

$ perl -E '@​foo = qw [a b c]; say "${foo}[0]"'
[0]
$

Interpolation works this way on purpose, the braces around the name
of the variable are allowed so you can interpolate a variable followed
by something in brackets without it being an indexing operation.

There's an ugly workaround​:

$ perl -E '"foo" =~ /(foo)/; say "${\${^CAPTURE}[0]}"'
foo
$

Thanks for clarification. I was surprised when I first tested them, but surely the current behavior is natural if they aren't special-cased.

Kenichi

$ perl -E '"a"=~/(?<b>.)/; say %{^CAPTURE}; say "%{^CAPTURE}"'
ba
%{^CAPTURE}

Hashes don't interpolate in perl5.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Jun 28, 2017

From @demerphq

On 28 June 2017 at 08​:37, Abigail <abigail@​abigail.be> wrote​:

On Tue, Jun 27, 2017 at 12​:48​:37AM -0700, Kenichi Ishigaki wrote​:

# New Ticket Created by Kenichi Ishigaki
# Please include the string​: [perl #131664]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=131664 >

This is a bug report for perl from ishigaki@​cpan.org,
generated with the help of perlbug 1.40 running under perl 5.26.0.

-----------------------------------------------------------------
[Please describe your issue here]
Interpolation of newly introduced @​{^CAPTURE} and its friends doesn't work well.
See the following examples​:

$ perl -E '"a"=~/(.)/; say ${^CAPTURE}[0]; say "${^CAPTURE}[0]"'
a
[0]

That has nothing to do with @​{^CAPTURE}, but how interpolation works​:

$ perl -E '@​foo = qw [a b c]; say "${foo}[0]"'
[0]
$

Interpolation works this way on purpose, the braces around the name
of the variable are allowed so you can interpolate a variable followed
by something in brackets without it being an indexing operation.

I thought it was so that you could do "${foo}o" safely.

I am actually really surprised to hear this, since using the braces
is required with multicharacter caret vars. From that POV I think this
is a bug. I think that "${^CAPTURE}[0] " should interpolate the same
way that "$CAPTURE[0]" would.

After all these years I never once noticed this behavior. Sigh.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jun 28, 2017

From @Abigail

On Wed, Jun 28, 2017 at 12​:05​:42PM +0200, demerphq wrote​:

On 28 June 2017 at 08​:37, Abigail <abigail@​abigail.be> wrote​:

On Tue, Jun 27, 2017 at 12​:48​:37AM -0700, Kenichi Ishigaki wrote​:

# New Ticket Created by Kenichi Ishigaki
# Please include the string​: [perl #131664]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=131664 >

This is a bug report for perl from ishigaki@​cpan.org,
generated with the help of perlbug 1.40 running under perl 5.26.0.

-----------------------------------------------------------------
[Please describe your issue here]
Interpolation of newly introduced @​{^CAPTURE} and its friends doesn't work well.
See the following examples​:

$ perl -E '"a"=~/(.)/; say ${^CAPTURE}[0]; say "${^CAPTURE}[0]"'
a
[0]

That has nothing to do with @​{^CAPTURE}, but how interpolation works​:

$ perl -E '@​foo = qw [a b c]; say "${foo}[0]"'
[0]
$

Interpolation works this way on purpose, the braces around the name
of the variable are allowed so you can interpolate a variable followed
by something in brackets without it being an indexing operation.

I thought it was so that you could do "${foo}o" safely.

That as well of course.

I am actually really surprised to hear this, since using the braces
is required with multicharacter caret vars. From that POV I think this
is a bug. I think that "${^CAPTURE}[0] " should interpolate the same
way that "$CAPTURE[0]" would.

After all these years I never once noticed this behavior. Sigh.

Multicharacter caret vars are relatively new (5.8, or 5.10, IIRC). And
I think @​{^CAPTURE} is the first array. So, interpolation of elements
of such an array have never come up before.

Abigail

@p5pRT
Copy link
Author

p5pRT commented Jun 28, 2017

From Eirik-Berg.Hanssen@allverden.no

On Wed, Jun 28, 2017 at 12​:05 PM, demerphq <demerphq@​gmail.com> wrote​:

I am actually really surprised to hear this, since using the braces
is required with multicharacter caret vars. From that POV I think this
is a bug. I think that "${^CAPTURE}[0] " should interpolate the same
way that "$CAPTURE[0]" would.

  I thought I'd found a workaround (or rather, working interpolation
syntax) in "${^CAPTURE[0]}", but that's a syntax error.

  (Huh?)

  Odd, since "${foo[0]}" obviously works (although I'm not sure it's
documented). Seems the caret breaks it​:

eirik@​purplehat[18​:00​:40]$ perl -E 'my @​CAPTURE = "a"=/(.)/; say
${CAPTURE}[0]; say "${CAPTURE}[0]"; say "${CAPTURE[0]}"'
a
[0]
a
eirik@​purplehat[18​:00​:52]$ perl -E '"a"=/(.)/; say ${^CAPTURE}[0]; say
"${^CAPTURE}[0]"; say "${^CAPTURE[0]}"'
syntax error at -e line 1, near "{^"
Execution of -e aborted due to compilation errors.
eirik@​purplehat[18​:00​:55]~$ perl -v

This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or
the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.

eirik@​purplehat[18​:00​:57]~$

  So, um, yeah, I thought "${^CAPTURE[0]}" would interpolate the same way
that "${CAPTURE[0]}" would.

  … is that a bug?

Eirik

@p5pRT
Copy link
Author

p5pRT commented Jun 29, 2017

From @Abigail

On Wed, Jun 28, 2017 at 06​:04​:08PM +0200, Eirik Berg Hanssen wrote​:

On Wed, Jun 28, 2017 at 12​:05 PM, demerphq <demerphq@​gmail.com> wrote​:

I am actually really surprised to hear this, since using the braces
is required with multicharacter caret vars. From that POV I think this
is a bug. I think that "${^CAPTURE}[0] " should interpolate the same
way that "$CAPTURE[0]" would.

I thought I'd found a workaround (or rather, working interpolation
syntax) in "${^CAPTURE[0]}", but that's a syntax error.

(Huh?)

Odd, since "${foo[0]}" obviously works (although I'm not sure it's
documented).

I never knew that "${foo[0]}" worked. If it's not documented, I'm
not sure whether it's intended to work, or just "happens" to work.

eirik@​purplehat[18​:00​:40]$ perl -E 'my @​CAPTURE = "a"=/(.)/; say
${CAPTURE}[0]; say "${CAPTURE}[0]"; say "${CAPTURE[0]}"'
a
[0]
a
eirik@​purplehat[18​:00​:52]$ perl -E '"a"=/(.)/; say ${^CAPTURE}[0]; say
"${^CAPTURE}[0]"; say "${^CAPTURE[0]}"'
syntax error at -e line 1, near "{^"
Execution of -e aborted due to compilation errors.
eirik@​purplehat[18​:00​:55]~$ perl -v

This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or
the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.

eirik@​purplehat[18​:00​:57]~$

So, um, yeah, I thought "${^CAPTURE[0]}" would interpolate the same way
that "${CAPTURE[0]}" would.

… is that a bug?

No idea :\

Abigail

@p5pRT
Copy link
Author

p5pRT commented Jun 29, 2017

From @xsawyerx

On 06/28/2017 06​:27 PM, Abigail wrote​:

On Wed, Jun 28, 2017 at 06​:04​:08PM +0200, Eirik Berg Hanssen wrote​:

On Wed, Jun 28, 2017 at 12​:05 PM, demerphq <demerphq@​gmail.com> wrote​:

I am actually really surprised to hear this, since using the braces
is required with multicharacter caret vars. From that POV I think this
is a bug. I think that "${^CAPTURE}[0] " should interpolate the same
way that "$CAPTURE[0]" would.

I thought I'd found a workaround (or rather, working interpolation
syntax) in "${^CAPTURE[0]}", but that's a syntax error.

(Huh?)

Odd, since "${foo[0]}" obviously works (although I'm not sure it's
documented).

I never knew that "${foo[0]}" worked. If it's not documented, I'm
not sure whether it's intended to work, or just "happens" to work.

eirik@​purplehat[18​:00​:40]$ perl -E 'my @​CAPTURE = "a"=/(.)/; say
${CAPTURE}[0]; say "${CAPTURE}[0]"; say "${CAPTURE[0]}"'
a
[0]
a
eirik@​purplehat[18​:00​:52]$ perl -E '"a"=/(.)/; say ${^CAPTURE}[0]; say
"${^CAPTURE}[0]"; say "${^CAPTURE[0]}"'
syntax error at -e line 1, near "{^"
Execution of -e aborted due to compilation errors.
eirik@​purplehat[18​:00​:55]~$ perl -v

This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or
the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.

eirik@​purplehat[18​:00​:57]~$

So, um, yeah, I thought "${^CAPTURE[0]}" would interpolate the same way
that "${CAPTURE[0]}" would.

… is that a bug?

No idea :\

I would say I find interpolation here a desired behavior, instead of not
working. Considering these variables were only introduced one, there's
an argument to be made for the technical definition of a bug. An
argument I don't find very interesting to have, so I'll instead focus on
what I believe would be desired behavior.

@p5pRT
Copy link
Author

p5pRT commented Jun 29, 2017

From @demerphq

On 29 June 2017 at 06​:54, Sawyer X <xsawyerx@​gmail.com> wrote​:

On 06/28/2017 06​:27 PM, Abigail wrote​:

On Wed, Jun 28, 2017 at 06​:04​:08PM +0200, Eirik Berg Hanssen wrote​:

On Wed, Jun 28, 2017 at 12​:05 PM, demerphq <demerphq@​gmail.com> wrote​:

I am actually really surprised to hear this, since using the braces
is required with multicharacter caret vars. From that POV I think this
is a bug. I think that "${^CAPTURE}[0] " should interpolate the same
way that "$CAPTURE[0]" would.

I thought I'd found a workaround (or rather, working interpolation
syntax) in "${^CAPTURE[0]}", but that's a syntax error.

(Huh?)

Odd, since "${foo[0]}" obviously works (although I'm not sure it's
documented).

I never knew that "${foo[0]}" worked. If it's not documented, I'm
not sure whether it's intended to work, or just "happens" to work.

eirik@​purplehat[18​:00​:40]$ perl -E 'my @​CAPTURE = "a"=/(.)/; say
${CAPTURE}[0]; say "${CAPTURE}[0]"; say "${CAPTURE[0]}"'
a
[0]
a
eirik@​purplehat[18​:00​:52]$ perl -E '"a"=/(.)/; say ${^CAPTURE}[0]; say
"${^CAPTURE}[0]"; say "${^CAPTURE[0]}"'
syntax error at -e line 1, near "{^"
Execution of -e aborted due to compilation errors.
eirik@​purplehat[18​:00​:55]~$ perl -v

This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or
the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.

eirik@​purplehat[18​:00​:57]~$

So, um, yeah, I thought "${^CAPTURE[0]}" would interpolate the same way
that "${CAPTURE[0]}" would.

… is that a bug?

No idea :\

I would say I find interpolation here a desired behavior, instead of not
working. Considering these variables were only introduced one, there's
an argument to be made for the technical definition of a bug. An
argument I don't find very interesting to have, so I'll instead focus on
what I believe would be desired behavior.

Reading the code I think this is a bug.

The code that handles caret vars was added to code handling ${ in
general as a special case, and I think the author did not notice the
importance of the latter half of the existing special case handler,
which implements subscripts. A simple goto from the end of the else
clause into end of the previous handler fixes this. Obviously this is
quick and dirty, but I think it suggests that this was an oversight
and the behavior we see is a bug.

Inline Patch
diff --git a/toke.c b/toke.c
index 0dcf623..2869431 100644
--- a/toke.c
+++ b/toke.c
@@ -9363,6 +9363,7 @@ S_scan_ident(pTHX_ char *s, char *dest, STRLEN
destlen, I32 ck_uni)   if \(s \< PL\_bufend && isSPACE\(\*s\)\) \{   s = skipspace\(s\);   \} \+ brace\_with\_subscript​:   if \(\(\*s == '\[' || \(\*s == '\{' && strNE\(dest\, "sub"\)\)\)\) \{   /\* $\{foo\[0\]\} and $\{foo\{bar\}\} notation\. \*/   if \(ckWARN\(WARN\_AMBIGUOUS\) && keyword\(dest\, d \- dest\, 0\)\) \{ @​@​ \-9395\,6 \+9396\,7 @​@​ S\_scan\_ident\(pTHX\_ char \*s\, char \*dest\, STRLEN destlen\, I32 ck\_uni\)   if \(d >= e\)   Perl\_croak\(aTHX\_ "%s"\, ident\_too\_long\);   \*d = '\\0'; \+ goto brace\_with\_subscript;   \}

  if ( !tmp_copline )

Makes them work equivalently. That the goto form is possible argues in
favour of this being unintentional. A better patch without the goto is
as follows​:

Inline Patch
diff --git a/toke.c b/toke.c
index 0dcf623..5f19e1d 100644
--- a/toke.c
+++ b/toke.c
@@ -9352,19 +9352,32 @@ S_scan_ident(pTHX_ char *s, char *dest, STRLEN
destlen, I32 ck_uni)   bool skip;   char \*s2;   /\* If we were processing \{\.\.\.\} notation then\.\.\. \*/ \- if \(isIDFIRST\_lazy\_if\_safe\(d\, e\, is\_utf8\)\) \{ \- /\* if it starts as a valid identifier\, assume that it is one\. \- \(the later check for \} being at the expected point will trap \- cases where this doesn't pan out\.\) \*/ \- d \+= is\_utf8 ? UTF8SKIP\(d\) : 1; \- parse\_ident\(&s\, &d\, e\, 1\, is\_utf8\, TRUE\); \- \*d = '\\0'; \- tmp\_copline = CopLINE\(PL\_curcop\); \- if \(s \< PL\_bufend && isSPACE\(\*s\)\) \{ \- s = skipspace\(s\); \+ if \(isIDFIRST\_lazy\_if\_safe\(d\, e\, is\_utf8\) \+ || \(\!isPRINT\(\*d\) /\* isCNTRL\(d\)\, plus all non\-ASCII \*/ \+ && isWORDCHAR\(\*s\)\) \+ \) \{ \+ if \(\!isPRINT\(\*d\)\) \{ /\* caret word​: $\{^Foo\} $\{^CAPTURE\[0\]\} \*/ \+ d\+\+; \+ while \(isWORDCHAR\(\*s\) && d \< e\) \{ \+ \*d\+\+ = \*s\+\+; \+ \} \+ if \(d >= e\) \+ Perl\_croak\(aTHX\_ "%s"\, ident\_too\_long\); \+ \*d = '\\0'; \+ \} else \{ \+ /\* if it starts as a valid identifier\, assume that it is one\. \+ \(the later check for \} being at the expected point will trap \+ cases where this doesn't pan out\.\) \*/ \+ d \+= is\_utf8 ? UTF8SKIP\(d\) : 1; \+ parse\_ident\(&s\, &d\, e\, 1\, is\_utf8\, TRUE\); \+ \*d = '\\0'; \+ tmp\_copline = CopLINE\(PL\_curcop\); \+ if \(s \< PL\_bufend && isSPACE\(\*s\)\) \{ \+ s = skipspace\(s\); \+ \}   \}   if \(\(\*s == '\[' || \(\*s == '\{' && strNE\(dest\, "sub"\)\)\)\) \{ \- /\* $\{foo\[0\]\} and $\{foo\{bar\}\} notation\. \*/ \+ /\* $\{foo\[0\]\} and $\{foo\{bar\}\} and $\{^CAPTURE\[0\]\} notation\. \*/   if \(ckWARN\(WARN\_AMBIGUOUS\) && keyword\(dest\, d \- dest\, 0\)\) \{   const char \* const brack =   \(const char \*\) @​@​ \-9383\,19 \+9396\,6 @​@​ S\_scan\_ident\(pTHX\_ char \*s\, char \*dest\, STRLEN destlen\, I32 ck\_uni\)   return s;   \}   \} \- /\* Handle extended $\{^Foo\} variables \- \* 1999\-02\-27 mjd\-perl\-patch@​plover\.com \*/ \- else if \(\! isPRINT\(\*d\) /\* isCNTRL\(d\)\, plus all non\-ASCII \*/ \- && isWORDCHAR\(\*s\)\) \- \{ \- d\+\+; \- while \(isWORDCHAR\(\*s\) && d \< e\) \{ \- \*d\+\+ = \*s\+\+; \- \} \- if \(d >= e\) \- Perl\_croak\(aTHX\_ "%s"\, ident\_too\_long\); \- \*d = '\\0'; \- \}

  if ( !tmp_copline )
  tmp_copline = CopLINE(PL_curcop);

But I have to wonder if the part that says​:

+ tmp_copline = CopLINE(PL_curcop);
+ if (s < PL_bufend && isSPACE(*s)) {
+ s = skipspace(s);
+ }

should also be shared.

Yves
--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jun 29, 2017

From @demerphq

On 29 June 2017 at 09​:51, demerphq <demerphq@​gmail.com> wrote​:

diff --git a/toke.c b/toke.c
index 0dcf623..5f19e1d 100644
--- a/toke.c
+++ b/toke.c
@​@​ -9352,19 +9352,32 @​@​ S_scan_ident(pTHX_ char *s, char *dest, STRLEN
destlen, I32 ck_uni)
[SNIP]
+ if (isIDFIRST_lazy_if_safe(d, e, is_utf8)
+ || (!isPRINT(*d) /* isCNTRL(d), plus all non-ASCII */
+ && isWORDCHAR(*s))
+ ) {
+ if (!isPRINT(*d)) { /* caret word​: ${^Foo} ${^CAPTURE[0]} */
+ d++;
+ while (isWORDCHAR(*s) && d < e) {
+ *d++ = *s++;
+ }
+ if (d >= e)
+ Perl_croak(aTHX_ "%s", ident_too_long);
+ *d = '\0';
+ } else {
+ /* if it starts as a valid identifier, assume that it is one.
+ (the later check for } being at the expected point will trap
+ cases where this doesn't pan out.) */
+ d += is_utf8 ? UTF8SKIP(d) : 1;
+ parse_ident(&s, &d, e, 1, is_utf8, TRUE);
+ *d = '\0';
+ tmp_copline = CopLINE(PL_curcop);
+ if (s < PL_bufend && isSPACE(*s)) {
+ s = skipspace(s);
+ }

Turns out this was the wrong way around, we have to rule out utf8
identifiers before we can decode caret identifiers (given the way we
currently identify caret identifiers).

I pushed a fix, with no tests as yet, to smoke-me/rt_131664

Ill push the tests later if noone beats me to it.

FWIW, i have been testing with​:

./perl -le'"foo"=~/(.+)/; print "${^CAPTURE [0] }"'

which should print "foo" obviously, and not die.

cheers,
Yves

@p5pRT
Copy link
Author

p5pRT commented Jun 29, 2017

From @demerphq

On 29 June 2017 at 11​:35, demerphq <demerphq@​gmail.com> wrote​:

On 29 June 2017 at 09​:51, demerphq <demerphq@​gmail.com> wrote​:

diff --git a/toke.c b/toke.c
index 0dcf623..5f19e1d 100644
--- a/toke.c
+++ b/toke.c
@​@​ -9352,19 +9352,32 @​@​ S_scan_ident(pTHX_ char *s, char *dest, STRLEN
destlen, I32 ck_uni)
[SNIP]
+ if (isIDFIRST_lazy_if_safe(d, e, is_utf8)
+ || (!isPRINT(*d) /* isCNTRL(d), plus all non-ASCII */
+ && isWORDCHAR(*s))
+ ) {
+ if (!isPRINT(*d)) { /* caret word​: ${^Foo} ${^CAPTURE[0]} */
+ d++;
+ while (isWORDCHAR(*s) && d < e) {
+ *d++ = *s++;
+ }
+ if (d >= e)
+ Perl_croak(aTHX_ "%s", ident_too_long);
+ *d = '\0';
+ } else {
+ /* if it starts as a valid identifier, assume that it is one.
+ (the later check for } being at the expected point will trap
+ cases where this doesn't pan out.) */
+ d += is_utf8 ? UTF8SKIP(d) : 1;
+ parse_ident(&s, &d, e, 1, is_utf8, TRUE);
+ *d = '\0';
+ tmp_copline = CopLINE(PL_curcop);
+ if (s < PL_bufend && isSPACE(*s)) {
+ s = skipspace(s);
+ }

Turns out this was the wrong way around, we have to rule out utf8
identifiers before we can decode caret identifiers (given the way we
currently identify caret identifiers).

I pushed a fix, with no tests as yet, to smoke-me/rt_131664

And I have deleted and recreated that branch with

3484359

on it now, which includes tests.

Yves
--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jun 29, 2017

From @xsawyerx

On 06/29/2017 12​:51 AM, demerphq wrote​:

On 29 June 2017 at 06​:54, Sawyer X <xsawyerx@​gmail.com> wrote​:

On 06/28/2017 06​:27 PM, Abigail wrote​:

On Wed, Jun 28, 2017 at 06​:04​:08PM +0200, Eirik Berg Hanssen wrote​:

On Wed, Jun 28, 2017 at 12​:05 PM, demerphq <demerphq@​gmail.com> wrote​:

I am actually really surprised to hear this, since using the braces
is required with multicharacter caret vars. From that POV I think this
is a bug. I think that "${^CAPTURE}[0] " should interpolate the same
way that "$CAPTURE[0]" would.

I thought I'd found a workaround (or rather, working interpolation
syntax) in "${^CAPTURE[0]}", but that's a syntax error.

(Huh?)

Odd, since "${foo[0]}" obviously works (although I'm not sure it's
documented).
I never knew that "${foo[0]}" worked. If it's not documented, I'm
not sure whether it's intended to work, or just "happens" to work.

eirik@​purplehat[18​:00​:40]$ perl -E 'my @​CAPTURE = "a"=/(.)/; say
${CAPTURE}[0]; say "${CAPTURE}[0]"; say "${CAPTURE[0]}"'
a
[0]
a
eirik@​purplehat[18​:00​:52]$ perl -E '"a"=/(.)/; say ${^CAPTURE}[0]; say
"${^CAPTURE}[0]"; say "${^CAPTURE[0]}"'
syntax error at -e line 1, near "{^"
Execution of -e aborted due to compilation errors.
eirik@​purplehat[18​:00​:55]~$ perl -v

This is perl 5, version 26, subversion 0 (v5.26.0) built for x86_64-linux
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or
the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.

eirik@​purplehat[18​:00​:57]~$

So, um, yeah, I thought "${^CAPTURE[0]}" would interpolate the same way
that "${CAPTURE[0]}" would.

… is that a bug?
No idea :\
I would say I find interpolation here a desired behavior, instead of not
working. Considering these variables were only introduced one, there's
an argument to be made for the technical definition of a bug. An
argument I don't find very interesting to have, so I'll instead focus on
what I believe would be desired behavior.

Reading back, this was vague. I consider it undesirable that it does not
interpolate, as in, let's fix it. :)

Thank you for a quick resolution to this.

@p5pRT
Copy link
Author

p5pRT commented Dec 30, 2017

From zefram@fysh.org

The behaviour here is not a bug. The rule that braces fully delimit
the interpolatable expression is a deliberate one, of long standing, and
deliberately different from the syntax of array/hash element references
outside quotes. The treatment of "${^CAPTURE}[0]" is consistent with
that of "${foo}[0]", and for that matter with "${^MATCH}[0]" which can
quite easily be used deliberately. Hat-based variable names have no
less need for this delimitation than other variable names.

If this rule were to be changed, it would require a deprecation cycle.
But we should not change it, and this ticket should be closed.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 30, 2017

From @cpansprout

On Sat, 30 Dec 2017 04​:04​:26 -0800, zefram@​fysh.org wrote​:

The behaviour here is not a bug. The rule that braces fully delimit
the interpolatable expression is a deliberate one, of long standing, and
deliberately different from the syntax of array/hash element references
outside quotes. The treatment of "${^CAPTURE}[0]" is consistent with
that of "${foo}[0]", and for that matter with "${^MATCH}[0]" which can
quite easily be used deliberately. Hat-based variable names have no
less need for this delimitation than other variable names.

If this rule were to be changed, it would require a deprecation cycle.
But we should not change it, and this ticket should be closed.

Was Yves’s patch for ${^CAPTURE[0]} ever applied?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Dec 30, 2017

From @demerphq

On 30 December 2017 at 16​:18, Father Chrysostomos via RT
<perlbug-followup@​perl.org> wrote​:

On Sat, 30 Dec 2017 04​:04​:26 -0800, zefram@​fysh.org wrote​:

The behaviour here is not a bug. The rule that braces fully delimit
the interpolatable expression is a deliberate one, of long standing, and
deliberately different from the syntax of array/hash element references
outside quotes. The treatment of "${^CAPTURE}[0]" is consistent with
that of "${foo}[0]", and for that matter with "${^MATCH}[0]" which can
quite easily be used deliberately. Hat-based variable names have no
less need for this delimitation than other variable names.

If this rule were to be changed, it would require a deprecation cycle.
But we should not change it, and this ticket should be closed.

This ticket included discussion of two aspects of this problem. One is
as Zefram says, and the other is fixed already.

Was Yves’s patch for ${^CAPTURE[0]} ever applied?

Yes, in 4f08ed8, aka 5.27.2.

But again, just to be clear, that was a slightly different issue from
the original ticket. We didn't create a separate ticket for the fact
that ${foo[10]} works, but ${^CAPTURE[10]} didn't.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 30, 2017

From @demerphq

On 30 December 2017 at 13​:04, Zefram <zefram@​fysh.org> wrote​:

The behaviour here is not a bug. The rule that braces fully delimit
the interpolatable expression is a deliberate one, of long standing, and
deliberately different from the syntax of array/hash element references
outside quotes. The treatment of "${^CAPTURE}[0]" is consistent with
that of "${foo}[0]", and for that matter with "${^MATCH}[0]" which can
quite easily be used deliberately. Hat-based variable names have no
less need for this delimitation than other variable names.

If this rule were to be changed, it would require a deprecation cycle.
But we should not change it, and this ticket should be closed.

I think you have not read the ticket in detail, and are paying too
little attention to the subject line and too much attention to the
body.

The subject of this ticket is "Interpolation of @​{^CAPTURE} and it's
friends doens't work".

This was actually true, as the notation "${^CAPTURE[0]}" did not work
correctly, and was fixed in

$ git log --grep 'Parse caret vars with subscripts'
commit 4f08ed8
Author​: Yves Orton <demerphq@​gmail.com>
Date​: Thu Jun 29 11​:31​:14 2017 +0200

  Parse caret vars with subscripts the same as normal vars inside of
${..} escaping

  This behavior is discussed in perl #131664, which complains that
  "${^CAPTURE}[0]" does not work as expected. Abigail explains the
  behavior is by design and Eirik Berg Hanssen expands on that explanation
  pointing out that what /should/ work, "${^CAPTURE[0]}" does not,
  which Sawyer then ruled was a bug.

  So this patch makes "${^CAPTURE[0]}" (and "${^CAPTURE [0]}" [hi
  abigial]) work the same as they would if the var was called @​foo.

You are correct the body recommended a syntax that is not right, but
we figured out that out during the thread, and at the same time
determined the syntax that should have worked was broken, and then
fixed it.

So as far as I am concerned this ticket can be closed as *fixed*.
There was a bug, even if I didn't understand it properly when i wrote
the ticket, and it was fixed, and the description on the ticket
matches what was fixed pretty well.

If you wish, you can close this ticket as wont fix, and then create a
new ticket with a better description and then point that at this
ticket and the above patch, and mark it as fixed. But personally I
don't see the point.

Regardless I agree this matter is closed.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Dec 30, 2017

From zefram@fysh.org

demerphq wrote​:

This was actually true, as the notation "${^CAPTURE[0]}" did not work
correctly, and was fixed in

Sorry, I did miss the index-inside-braces aspect somehow. I'm happy
for this ticket to be closed as fixed, on the basis that that got fixed.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 30, 2017

@cpansprout - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2018

From @khwilliamson

Thank you for filing this report. You have helped make Perl better.

With the release yesterday of Perl 5.28.0, this and 185 other issues have been
resolved.

Perl 5.28.0 may be downloaded via​:
https://metacpan.org/release/XSAWYERX/perl-5.28.0

If you find that the problem persists, feel free to reopen this ticket.

@p5pRT p5pRT closed this as completed Jun 23, 2018
@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2018

@khwilliamson - Status changed from 'pending release' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant