http://www.perlmonks.org?node_id=11114538

syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

By "numeric flags", I'm referring to the "IOK", "pIOK", "NOK", "pNOK" and the "IsUV" flags (as presented by Devel::Peek::Dump).
But rather than have this information displayed, I'm looking for a sub that returns the status of these specific flags. That is, something like:
sub flag_status { my $v = $_[0]; return is_IOK($v) | is_pIOK($v) | is_IsUV($v) | is_NOK($v) | is_pNOK($v); } sub is_IOK { # return 1 if argument's IOK flag is set # else return 0 } sub is_pIOK { # return 2 if argument's pIOK flag is set # else return 0 } sub is_NOK { # return 4 if argument's NOK flag is set # else return 0 } sub is_pNOK { # return 8 if argument's pNOK flag is set # else return 0 } sub is_IsUV { # return 16 if argument's IsUV flag is set # else return 0 }
The aim is to be able to determine whether a subroutine call changes the status of any of those flags on the subroutine's argument. That is:
my $d = 2.7; my $flags_prior = flag_status($d); foo($d); my $flags_after = flag_status($d); die "foo() altered its argument's numeric flags" if($flags_prior != $flags_after);
Is there already a perl module that ships with the core that will return the status of those 5 flags ?
Is there already a module on CPAN that will return the status of those 5 flags ?

I know how to find the status of "IOK", "NOK" and "IsUV" in XS.
One can merely test the truth of SvIOK(sv), SvNOK(sv) and SvUOK(sv) respectively.
But how does one establish, in XS, whether the "pIOK" and "pNOK" flags are set ?

Maybe there's another way to approach this.
The key thing is that I want to be able to programmatically catch the occurrence of foo() altering its argument's "numeric flags".

Cheers,
Rob

Replies are listed 'Best First'.
Re: Looking for a function that returns status of a scalar's numeric flags
by haukex (Archbishop) on Mar 22, 2020 at 08:25 UTC

    You could probably use use B qw/svref_2object/; my $flags = svref_2object(\$val)->FLAGS;, but Tux's Data::Peek seems to have pretty nice interface:

    use warnings; use strict; use Data::Dump; use Data::Peek qw/DDump/; my $x = "2.7"; dd {DDump $x}->{FLAGS}; dd $x; # changes flags dd {DDump $x}->{FLAGS}; __END__ { IsCOW => 1, POK => 1, pPOK => 1 } 2.7 { IsCOW => 1, NOK => 1, pIOK => 1, pNOK => 1, POK => 1, pPOK => 1 }
      You could probably use use B qw/svref_2object/; my $flags = svref_2object(\$val)->FLAGS;

      Yes, I think that's the best one for the purpose I have in mind.
      I'm thinking of proposing a test to check that List::Util::uniqnum() doesn't alter the numeric flags of its arguments when it doesn't need to.
      My latest pull request was initially committing that very sin ... though I've since amended that PR such that uniqnum() no longer does that.
      Strikes me that a test to check for such behaviour could be useful, and since List::Util is perl core, the test should utilize core modules only.
      IIUC, that makes B the only option .... and therefore the best one ;-)

      It's certainly handy to be aware of other candidates - and thank you for drawing my attention to Data::Peek.
      I agree that it has a rather nice interface.

      Cheers,
      Rob
Re: Looking for a function that returns status of a scalar's numeric flags
by Haarg (Priest) on Mar 22, 2020 at 09:29 UTC

    I have a test for this exact thing in Sub::Quote. It uses the B module to check the flags. Rather than having individual functions for each flag, or generating a data structure, my test just generates a string of what flags are set, since that was simplest and gave the nicest debugging results.

    From quotify.t:

    my %flags; { no strict 'refs'; for my $flag (qw( SVs_TEMP SVs_OBJECT SVs_GMG SVs_SMG SVs_RMG SVf_IOK SVf_NOK SVf_POK SVf_OOK SVf_FAKE SVf_READONLY SVf_PROTECT SVf_BREAK SVp_IOK SVp_NOK SVp_POK )) { if (defined &{'B::'.$flag}) { $flags{$flag} = &{'B::'.$flag}; } } } sub flags { my $flags = B::svref_2object(\($_[0]))->FLAGS; join ' ', sort grep $flags & $flags{$_}, keys %flags; }
    then later:
    is flags($copy), flags($value), "$value_name: quotify doesn't modify input";

      I have a test for this exact thing in Sub::Quote.

      Also rather nice work !
      And a handy reference.

      I don't see any "IsUV" flag there.
      Why is that ?

      Cheers,
      Rob
Re: Looking for a function that returns status of a scalar's numeric flags
by bliako (Monsignor) on Mar 22, 2020 at 09:49 UTC

    How about doing it via the guts? Search also perlapi for SvIOKp.

    # author: bliako # for: https://perlmonks.org/?node_id=11114538 # 22/03/2020 use Inline 'C'; my $x; $x = "123"; flags($x); $x= 123; flags($x); $x= 123.123; flags($x); __END__ __C__ void flags(SV *sv){ printf("int=%d, double=%d, string=%d\n", SvIOKp(sv)>>12 & 1, SvNOKp(sv)>>13 & 1, SvPOKp(sv)>>14 & 1 ); }

    bw, bliako

      Search also perlapi for SvIOKp

      Yes, Inline::C has always been my first goto, and I've written plenty of XSubs that reference SvIOK and friends.
      But this is the first time that I've ever been interested in SvIOKp and friends, and I didn't know about them even though they're mentioned in perlapi.
      Thanks for bringing them to my attention.

      I had a little play with them in Inline::C last night, shortly after reading your reply, and an XSub that returned
      SvIOK(sv) | SvNOK(sv) | SvIOKp(sv) | SvNOKp() | SvUOK(sv)
      provided me with all that I needed.
      The only problem being that Inline::C is not core :-(

      Cheers,
      Rob
Re: Looking for a function that returns status of a scalar's numeric flags
by val (Initiate) on Mar 22, 2020 at 19:17 UTC
    You might try FTN::Bit_flags from CPAN.
      You might try FTN::Bit_flags from CPAN.

      I don't see how this is particularly relevant to my needs.

      When one assigns a value to a scalar, $x, by doing say:
      $x = -17; or $x = 1.414;
      perl ascribes some numeric flags to $x, and those flags (which vary for different types of numbers) are not readily visible.
      My main interest was in the ways that we can make those flags visible to the program - and it's not apparent to me how FTN::Bit_flags can help in that regard.
      Looks to me that this module is more about manipulating bit flags, which is not my concern here. (I'm just trying to get a hold of the damn things ;-)

      Cheers,
      Rob