@@ -348,7 +348,119 @@ well.
348348
349349=item *
350350
351- XXX
351+ Reading the string form of an integer value no longer sets the flag C<SVf_POK>.
352+ The string form is still cached internally, and still re-read directly by the
353+ macros C<SvPV(sv)> I<etc> (inline, without calling a C function). XS code that
354+ already the APIs to get values will not be affected by this change. XS code
355+ that accesses flags directly instead of using API calls to express its intent
356+ I<might> break, but such code likely is already buggy if passed some other
357+ values, such as floating point values or objects with string overloading.
358+
359+ This small change permits code (such as JSON serealisers) to reliably determine
360+ between
361+
362+ =over 4
363+
364+ =item *
365+
366+ a value that was initially B<written> as an integer, but then B<read> as a string
367+
368+ my $answer = 42;
369+ print "The answer is $answer\n";
370+
371+ =item *
372+
373+ that same value that was initially B<written> as a string, but then B<read> as an integer
374+
375+ my $answer = "42";
376+ print "That doesn't look right\n"
377+ unless $answer == 6 * 9;
378+
379+ =back
380+
381+ For the first case (originally written as an integer), we now have:
382+
383+ use Devel::Peek;
384+ my $answer = 42;
385+ Dump ($answer);
386+ my $void = "$answer";
387+ print STDERR "\n";
388+ Dump($answer)
389+
390+
391+ SV = IV(0x562538925778) at 0x562538925788
392+ REFCNT = 1
393+ FLAGS = (IOK,pIOK)
394+ IV = 42
395+
396+ SV = PVIV(0x5625389263c0) at 0x562538925788
397+ REFCNT = 1
398+ FLAGS = (IOK,pIOK,pPOK)
399+ IV = 42
400+ PV = 0x562538919b50 "42"\0
401+ CUR = 2
402+ LEN = 10
403+
404+ For the second (originally written as a string), we now have:
405+
406+ use Devel::Peek;
407+ my $answer = "42";
408+ Dump ($answer);
409+ my $void = $answer == 6 * 9;
410+ print STDERR "\n";
411+ Dump($answer)'
412+
413+
414+ SV = PV(0x5586ffe9bfb0) at 0x5586ffec0788
415+ REFCNT = 1
416+ FLAGS = (POK,IsCOW,pPOK)
417+ PV = 0x5586ffee7fd0 "42"\0
418+ CUR = 2
419+ LEN = 10
420+ COW_REFCNT = 1
421+
422+ SV = PVIV(0x5586ffec13c0) at 0x5586ffec0788
423+ REFCNT = 1
424+ FLAGS = (IOK,POK,IsCOW,pIOK,pPOK)
425+ IV = 42
426+ PV = 0x5586ffee7fd0 "42"\0
427+ CUR = 2
428+ LEN = 10
429+ COW_REFCNT = 1
430+
431+ (One can't rely on the presence or absence of the flag C<SVf_IsCOW> to
432+ determine the history of operations on a scalar.)
433+
434+ Previously both cases would be indistinguishable, with all 4 flags set:
435+
436+ SV = PVIV(0x55d4d62edaf0) at 0x55d4d62f0930
437+ REFCNT = 1
438+ FLAGS = (IOK,POK,pIOK,pPOK)
439+ IV = 42
440+ PV = 0x55d4d62e1740 "42"\0
441+ CUR = 2
442+ LEN = 10
443+
444+ (and possibly C<SVf_IsCOW>, but not always)
445+
446+ This now means that if XS code I<really> needs to determine which form a value
447+ was first written as, it should implement logic roughly
448+
449+ if (flags & SVf_IOK|SVf_NOK) && !(flags & SVf_POK)
450+ serealise as number
451+ else if (flags & SVf_POK)
452+ serealise as string
453+ else
454+ the existing guesswork ...
455+
456+ Note that this doesn't cover "dualvars" - scalars that report different
457+ values when asked for their string form or number form (such as C<$!>).
458+ Most serialisation formats cannot represent such duplicity.
459+
460+ I<the existing guesswork> remains because as well as dualvars, values might
461+ be C<undef>, references, overloaded references, typeglobs and other things that
462+ Perl itself can represent but do not map one-to-one into external formats, so
463+ need some amount of approximation or encapsulation.
352464
353465=back
354466
0 commit comments