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

scoping of @+/@- when used with tie() #6730

Closed
p5pRT opened this issue Aug 28, 2003 · 15 comments
Closed

scoping of @+/@- when used with tie() #6730

p5pRT opened this issue Aug 28, 2003 · 15 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 28, 2003

Migrated from rt.perl.org#23624 (status was 'open')

Searchable as RT23624$

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2003

From tassilo.parseval@post.rwth-aachen.de

Created by tassilo.parseval@post.rwth-aachen.de

Hi,

there is something very odd going on when trying to emulate $`, $' and $&
through tied hashes. See this code​:

  #! /usr/bin/perl -w

  package Tie​::Prematch;
  sub TIEHASH { bless \my $dummy => __PACKAGE__ }
  sub FETCH { return substr $_[1], 0, $-[0] }

  package main;

  tie my %pre, 'Tie​::Prematch';
  my $foo = "foobar";
  $foo =~ s/.ob/$pre{ $foo }/;
  print $foo, "\n";

  $foo = "foobar";
  $foo =~ s/.ob/tied(%pre)->FETCH($foo)/e;
  print $foo, "\n";

  tie %-, 'Tie​::Prematch';
  $foo = "foobar";
  $foo =~ s/.ob/$-{$foo}/;
  print $foo;
  __END__
  Use of uninitialized value in substr at bug.pl line 5.
  far
  ffar
  ffar

According to my knowledge, @​- and @​+ should be dynamically scoped so it's
obvious that they still have their values in Tie​::Prematch​::FETCH() when doing

  $foo =~ s/.ob/tied(%pre)->FETCH($foo)/e;

But they somehow loose them when doing

  $foo =~ s/.ob/$pre{ $foo }/;

even though it should be functionally identical.

It's even stranger​: as the third example in the above shows, it works when
I tie one of the truely global symbols (%- in this case). It turns out that
this kind of tying behaves normally with punctuation variables but fails
with lexicals and package variables.

This bug is present in at least 5.6.1, 5.8.0 and 5.8.1RC4.

Tassilo

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl v5.8.0:

Configured by root at Tue Feb 25 16:06:57 Local time zone must be set--see zic manual page 2003.

Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.4.20, archname=i686-linux
    uname='linux ethan 2.4.20 #2 mon dec 2 14:26:23 cet 2002 i686 unknown '
    config_args='-ds -e -Dprefix=/usr -Dccflags= -O3 -march=athlon'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-O3 -march=athlon -fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-O3 -march=athlon -fno-strict-aliasing'
    ccversion='', gccversion='3.2', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lc -lcrypt -lutil
    perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil
    libc=/lib/libc-2.2.5.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.2.5'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
    cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.0:
    /usr/lib/perl5/5.8.0/i686-linux
    /usr/lib/perl5/5.8.0
    /usr/lib/perl5/site_perl/5.8.0/i686-linux
    /usr/lib/perl5/site_perl/5.8.0
    /usr/lib/perl5/site_perl
    .


Environment for perl v5.8.0:
    HOME=/home/ethan
    LANG=C
    LANGUAGE (unset)
    LC_CTYPE=de_DE@euro
    LD_LIBRARY_PATH=:/usr/local/j2sdk1.4.0/jre/lib/i386:/usr/local/pwlib/lib
    LOGDIR (unset)
    PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games:/usr/local/j2re1.4.1/bin
    PERLDOC_PAGER=/bin/less -isR
    PERL_BADLANG (unset)
    SHELL=/bin/bash


@p5pRT
Copy link
Author

p5pRT commented Aug 29, 2003

From @rgs

tassilo.parseval@​post.rwth-aachen.de (via RT) wrote​:

According to my knowledge, @​- and @​+ should be dynamically scoped so it's
obvious that they still have their values in Tie​::Prematch​::FETCH() when doing

$foo =~ s/\.ob/tied\(%pre\)\->FETCH\($foo\)/e;

But they somehow loose them when doing

$foo =~ s/\.ob/$pre\{ $foo \}/;

even though it should be functionally identical.

No, the /e creates a scope. Add a /e to your 2nd example and it becomes
equivalent to the 1st one (apparently).

@p5pRT
Copy link
Author

p5pRT commented Aug 29, 2003

From tassilo.parseval@post.rwth-aachen.de

On Fri, Aug 29, 2003 at 08​:40​:49AM +0200 Rafael Garcia-Suarez wrote​:

tassilo.parseval@​post.rwth-aachen.de (via RT) wrote​:

According to my knowledge, @​- and @​+ should be dynamically scoped so it's
obvious that they still have their values in Tie​::Prematch​::FETCH() when doing

$foo =~ s/\.ob/tied\(%pre\)\->FETCH\($foo\)/e;

But they somehow loose them when doing

$foo =~ s/\.ob/$pre\{ $foo \}/;

even though it should be functionally identical.

No, the /e creates a scope. Add a /e to your 2nd example and it becomes
equivalent to the 1st one (apparently).

I don't understand this. Why do I need this additional scope in the
second case? In which scope is FETCH() called without the /e? Since
the values of these dynamically scoped variables aren't accessible in
it, it must be a scope above the one from the whole substitution (or
rather​: above the scope where @​- and @​+ are set). Or am I wrong here?

And secondly, why don't I need the /e when I use %- (for instance) as
the tied hash?

Adding an /e, if I may say that, is also highly strange. The right-hand
side of a substition is in double-quotish context. But​:

  $a{a} = "foo";
  $s = "foo";

  # these two will give the same results
  $s =~ s/./$a{a}/e
  $s =~ s/./$a{a}/;
 
  print $s;

This is not something that would become obvious when reading about /e in
perlop.pod.

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@​"tnirp}3..0}_$;//​::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval

@p5pRT
Copy link
Author

p5pRT commented Aug 4, 2007

From nobull at cpan.org

On Thu Aug 28 01​:53​:46 2003, vparseval wrote​:

\#\! /usr/bin/perl \-w

package Tie​::Prematch;
sub TIEHASH \{ bless \\my $dummy => \_\_PACKAGE\_\_ \}
sub FETCH   \{ return substr $\_\[1\]\, 0\, $\-\[0\] \}

package main;

tie my %pre\, 'Tie​::Prematch';
my $foo = "foobar";
$foo =~ s/\.ob/$pre\{ $foo \}/;

The problem here is that the Perl compiler sees the RHS of the s/// as
being invariant and thinks it can get away with evaluating without
setting up the last-match context.

At the optree level the difference is the inclusion or otherwise of the
substcont OP code.

Since this is a compile time optimisation and the tied-ness of %pre
cannot be determined at compile time there's not much that can really be
done to fix this (other than ditch the optimisation completely - which
would be a very high price to pay).

Arguably this (c|sh)ould be documented in perlop and/or perltie.

@p5pRT
Copy link
Author

p5pRT commented Aug 4, 2007

From nobull at cpan.org

On Sat Aug 04 09​:15​:05 2007, nobull67 wrote​:

Arguably this (c|sh)ould be documented in perlop and/or perltie.

perltie diff (to BUGS section) attached

@p5pRT
Copy link
Author

p5pRT commented Aug 4, 2007

From nobull at cpan.org

perltie.pod.diff

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2013

From @cpansprout

This is fixed in 5.18, most likely by bb933b9.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2013

From [Unknown Contact. See original ticket]

This is fixed in 5.18, most likely by bb933b9.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2013

@cpansprout - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Aug 7, 2013
@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2013

From @cpansprout

On Wed Aug 07 00​:51​:55 2013, sprout wrote​:

This is fixed in 5.18, most likely by bb933b9.

It still needs tests, though. I’d better re-open it....

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 7, 2013

@cpansprout - Status changed from 'resolved' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Aug 20, 2013

From @jkeenan

On Wed Aug 07 00​:59​:43 2013, sprout wrote​:

On Wed Aug 07 00​:51​:55 2013, sprout wrote​:

This is fixed in 5.18, most likely by bb933b9.

It still needs tests, though. I’d better re-open it....

Do you have a recommendation as to which file in which to place tests
for this?

@p5pRT
Copy link
Author

p5pRT commented Aug 20, 2013

From @cpansprout

On Mon Aug 19 18​:41​:23 2013, jkeenan wrote​:

On Wed Aug 07 00​:59​:43 2013, sprout wrote​:

On Wed Aug 07 00​:51​:55 2013, sprout wrote​:

This is fixed in 5.18, most likely by bb933b9.

It still needs tests, though. I’d better re-open it....

Do you have a recommendation as to which file in which to place tests
for this?

Probably t/re/subst.t.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Oct 21, 2016

From @dcollinsn

Tests added in 1994b21, closing.

--
Respectfully,
Dan Collins

@p5pRT
Copy link
Author

p5pRT commented Oct 21, 2016

From [Unknown Contact. See original ticket]

Tests added in 1994b21, closing.

--
Respectfully,
Dan Collins

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