As diotalevi pointed out in the chatterbox yesterday, this won't work for globals or package variables. So I got to thinking about how best to do it. I did a little more reading before sitting down to rework it.

It still needs work. I could definitely create a few more subroutines to reduce redundant code. It's not perfect either since if you use a lexical scalar in a global hash or a global scalar in a lexical hash, things go haywire.

I went through several different incantations before settling on this one:

#!/usr/bin/perl -w use strict; use B::Utils qw(opgrep walkallops_filtered); package foo; our $bar = ' delicious'; package str; our $ing = 'w00t!'; package main; my $stringy = 'abcde'; our %metoo = ( key => 3, foo => ' delicious', string => 'abcde', ); my $lvalue = \(vec($foo::bar, 0, 32) = 0x5065726C); ltype($lvalue); $lvalue = \(keys %metoo = 8); ltype($lvalue); $lvalue = \(pos $str::ing = 3); ltype($lvalue); $lvalue = \(pos $stringy = 5); ltype($lvalue); $lvalue = \substr($stringy, 2); ltype($lvalue); $lvalue = \substr($stringy, 1, 2); ltype($lvalue); sub lvalue { my $ref = shift; my $lref = B::svref_2object($ref); return undef if $lref !~ /PVLV/; my $value = $$ref; my $type = $lref->TYPE; my $targ = $lref->TARG; my $string = $lref->TARG->PV; my $offset = $lref->TARGOFF; my $length = $lref->TARGLEN; my $func; if ($type eq 'k') { my $hashname = getname($targ); my $val = $targ->MAX; ++$val; $func = "keys $hashname = $val;"; } if ($type eq 'v') { my $expr = getname($targ); $func = "vec($expr,$offset,$length) = $value;"; } if ($type eq 'x') { my $expr = getname($targ); $func = "substr($expr,".$offset.','.$length.');'; } if ($type eq '.') { my $scalar = getname($targ); $func = "pos $scalar = ".$value.';'; } return $func; } sub ltype { my $lvalue = shift; print '$$lvalue = ',$$lvalue,"\n"; print lvalue($lvalue),$/; print $/; } sub global_name { my $padname = shift; my $name = $padname->STASH->NAME.'::'.$padname->SAFENAME; $name =~ s/^main:://; return $name; } sub declassify { my %hash = @_; for my $key (keys %hash) { my $class = B::class($hash{$key}); $hash{$key} = $hash{$key}->$class; } return %hash; } sub getname { my $targ = shift; my $class = B::class($targ); my $name; walkallops_filtered( sub { my $op = shift; if ($class eq 'HV') { opgrep({ name => ["padhv", "rv2hv"], next => { name => "keys", + }, }, $op) or return; } elsif ($class eq 'PVMG') { opgrep({ name => ["padsv", "gvsv"], next => { name => ["pos", +"substr"], }, }, $op) or return; } elsif ($class eq 'PV') { opgrep({ name => ["padsv", "gvsv"], next => { name => "const", next => { next => { name => "vec", }, }, }, }, $op) or return; } }, sub { my $op = shift; my ($padname, $tempname); if ($op->name =~ /pad/) { $padname = ((B::main_cv->PADLIST->ARRAY)[0]->ARRAY)[$op->targ] +; $tempname = $padname->PV if $padname; return () unless $tempname; if ($class =~ /PV/) { $name = $tempname if ($targ->PV eq eval($tempname)); } elsif ($class eq 'HV') { my %temphash = $targ->ARRAY; $name = $tempname if (%temphash eq eval($tempname)); } } elsif ($op->name eq "gvsv") { $padname = ((B::main_cv->PADLIST->ARRAY)[1]->ARRAY)[$op->padix +]; $tempname = '$'.global_name($padname); $name = $tempname if ($targ->PV eq $padname->SV->PV); } elsif ($op->name eq "rv2hv") { $padname = ((B::main_cv->PADLIST->ARRAY)[1]->ARRAY)[$op->first +->padix]; $tempname = '%'.global_name($padname); my %padhash = declassify($padname->HV->ARRAY); my %targhash = declassify($targ->ARRAY); $name = $tempname if (%padhash eq %targhash); } } ); return $name; }


In reply to Re: Re: Discovering the lvaluable function behind the reference by Mr. Muskrat
in thread Discovering the lvaluable function behind the reference by Mr. Muskrat

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.