develooper Front page | perl.perl5.porters | Postings from August 2021

Re: Pre-RFC: Real "boolean" SV type

Thread Previous | Thread Next
From:
Nicholas Clark
Date:
August 5, 2021 07:29
Subject:
Re: Pre-RFC: Real "boolean" SV type
Message ID:
20210805072915.GI11066@etla.org
On Thu, Aug 05, 2021 at 11:26:07AM +1000, Tony Cook wrote:
> On Wed, Aug 04, 2021 at 03:58:19PM +0100, Paul "LeoNerd" Evans wrote:
> > I propose the addition of a new SV type, of SVt_BOOL. Should I write an
> > RFC?
> > 
> > This type will act much like the existing "booleans" of PL_sv_no and
> > PL_sv_yes, except its type will remain distinct, so it will be possible
> > to distinguish "that SV is a boolean". This is a requirement for
> > certain kinds of data serialisation - such as JSON or MsgPack - and may
> > be useful for many other purposes too.
> 
> I think having some sort of boolean type will be useful for
> serialization, I'm not sure svtype is the right place to distinguish
> them.
> 
> Like PV, PVNV etc (and unlike PVAV, PVIO etc) an SV will tend to get
> upgraded as more capabilities are needed from it.
> 
> If SVt_BOOL is a small SV type like SVt_IV, can such an SV have magic,
> or be blessed?
> 
> If SVt_BOOL is a large type like SVt_PVMG, simple booleans will be
> paying an extra cost they don't need.
> 
> It may need a flag instead.

It can't be implemented as a type.

Much like the "was this originally an integer/was this originally a string"
problem can't also be implemented as a type.

In that, if you need to bless a boolean, then it has to be SVt_PVMG.

And for certain operations, the *value* needs to pass through a PVLV without
loosing it's "I'm a boolean"-ness. I think tied hashes; but certainly this;

#!/usr/bin/perl -w

use strict;
use Devel::Peek;

sub foo {
    my $val = 3.14;
    print STDERR "Here's it's NV\n\n";
    Dump $val;
    print STDERR "\n\nWhat comes in is *funky*;\n\n";
    Dump($_[0]);
    $_[0] = 3.14;
}

my %h;

foo($h{pi});

print STDERR "\n\nWhat you end up with is PVNV:\n\n";

Dump(\%h);

__END__


Here's it's NV

SV = NV(0x11007a8) at 0x11007b0
  REFCNT = 1
  FLAGS = (NOK,pNOK)
  NV = 3.14


What comes in is *funky*;

SV = PVLV(0x1113f18) at 0x10dffb0
  REFCNT = 1
  FLAGS = (GMG,SMG)
  IV = 0
  NV = 0
  PV = 0
  MAGIC = 0x1101f18
    MG_VIRTUAL = &PL_vtbl_defelem
    MG_TYPE = PERL_MAGIC_defelem(y)
    MG_FLAGS = 0x02
      REFCOUNTED
    MG_OBJ = 0x10e0190
    SV = PV(0x10e09a0) at 0x10e0190
      REFCNT = 1
      FLAGS = (POK,pPOK)
      PV = 0x11130b8 "pi"\0
      CUR = 2
      LEN = 10
  TYPE = y
  TARGOFF = 0
  TARGLEN = 1
  TARG = 0x11007e0
  FLAGS = 0
  SV = PVHV(0x10e6420) at 0x11007e0
    REFCNT = 2
    FLAGS = (SHAREKEYS)
    ARRAY = 0x0
    KEYS = 0
    FILL = 0
    MAX = 7


What you end up with is PVNV:

SV = IV(0x10dffb0) at 0x10dffb0
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x11007e0
  SV = PVHV(0x10e6420) at 0x11007e0
    REFCNT = 2
    FLAGS = (SHAREKEYS)
    ARRAY = 0x1108d58  (0:7, 1:1)
    hash quality = 100.0%
    KEYS = 1
    FILL = 1
    MAX = 7
    Elt "pi" HASH = 0x694d4f73
    SV = PVNV(0x10deb28) at 0x10fb130
      REFCNT = 1
      FLAGS = (NOK,pNOK)
      IV = 0
      NV = 3.14
      PV = 0


So PVLVs also have to be able to hold booleans.

Types aren't the way to go. A flag might be, but it might also be possible to
implement it as

true:   SvPOK(sv) && SvPVX(sv) == PL_Yes)
false:  SvPOK(sv) && SvPVX(sv) == PL_No)

and have Perl_sv_setsv_flags() do SV copies like that for booleans.

(That's the *only* place that copies SVs. So it can be changed.)


Also


We need an API to say "how should I best serialise this SV?"

(This became apparent during the "IVs vs PVs" thread but I hadn't replied to
it there.)

Abstract all the "logic" about what flags might mean what into a clear API,
so that

1) We can change the internals in the future
2) We can add it to ppport.h to express the "best effort' for the past.


Pass a SV, return a value from an enumeration, which I think *starts*

* undef
* boolean
* integer
* float
* string

but needs at least one escape hatch for "clearly this is a dualvar"
and it's also not clear how to handle overloaded references.
Unless the rule is that anything passed in that's SvROK() returns "reference"
and the caller gets to figure it out.


(And before anyone starts to argue that string should be spit into "bytes" and
"text" - you *can't* know that based on just SVf_UTF8. This isn't what we
want, but it *is* the way it is currently.)


So yes, please, an RFC on booleans would be great. But the language level
semantics are what are important first - I don't think that the correct
implementation is obvious yet.

Nicholas Clark

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About