Skip to content

Commit

Permalink
cope with more edge cases where perl fills in IV/NV slots but we shou…
Browse files Browse the repository at this point in the history
…ld ignore it
  • Loading branch information
DrHyde committed May 5, 2021
1 parent e76c22b commit 35c9ac0
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 32 deletions.
65 changes: 33 additions & 32 deletions lib/Scalar/Type.pm
Original file line number Diff line number Diff line change
Expand Up @@ -89,39 +89,40 @@ sub type {

use Inline C => <<'END_OF_C';
// Unfortunately this would also promote 1.0 to an int, which we don't want.
// We want to only do that for 1e2 and friends, and that means we have to get
// our oar in rather earlier, in toke.c
//
// void _attempt_int_promote(SV* argument) {
// if(SvNOK(argument) && !SvIOK(argument)) {
// /* retrieve the 'double' value from the NV slot and get an
// equivalent int, losing anything after the decimal point
// */
// NV nv = SvNVX(argument);
// IV potential_iv = (IV)nv;
//
// int SV_is_readonly = SvREADONLY(argument);
//
// /* now turn the int back into a double and if it's the same
// as what we started with, fill in the IV slot
// */
// if((NV)potential_iv == nv) {
// if(SV_is_readonly) { SvREADONLY_off(argument); }
// SvIV_set(argument, potential_iv);
// SvIOK_on(argument);
// if(SV_is_readonly) { SvREADONLY_on(argument); }
// }
// }
// }
SV* _scalar_type(SV* argument) {
// /* handle nonsense like 1e2 being recognised by perl as a number but not an int */
// _attempt_int_promote(argument);
return SvIOK(argument) ? newSVpv("INTEGER", 7) :
SvNOK(argument) ? newSVpv("NUMBER", 6) :
newSVpv("SCALAR", 6);
SV* rval;
char num_as_str[100]; /* potential buffer overflow on 256-bit machines :-) */
if(SvIOK(argument)) {
if(SvPOK(argument)) {
/* int is also a string, better see if it's not int-ified 007 */
/* is %ld OK in 32-bit land? */
sprintf(num_as_str, "%ld", SvIVX(argument));
rval = (
(strcmp(SvPVX(argument), num_as_str)) == 0
? newSVpv("INTEGER", 7)
: newSVpv("SCALAR", 6)
);
} else {
rval = newSVpv("INTEGER", 7);
}
} else if(SvNOK(argument)) {
if(SvPOK(argument)) {
/* float is also a string, better see if it's not float-ified 007.5 */
sprintf(num_as_str, "%Lf", SvNVX(argument));
rval = (
(strcmp(SvPVX(argument), num_as_str)) == 0
? newSVpv("NUMBER", 6)
: newSVpv("SCALAR", 6)
);
} else {
rval = newSVpv("NUMBER", 6);
}
} else {
rval = newSVpv("SCALAR", 6);
}
return rval;
}
END_OF_C
Expand Down
32 changes: 32 additions & 0 deletions t/all.t
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,38 @@ subtest "integers written as exponents are weird" => sub {
};
};

subtest "string subsequently used as an int or float" => sub {
subtest "'007'" => sub {
my $foo = '007';
$foo < 8;
ok($foo eq '007', "after being treated as an int it still has its original value");
is(type($foo), 'SCALAR', "and it's not become an integer as far as we're concerned");
note(capture_stderr { Dump($foo) });
};

subtest "'007.5'" => sub {
my $foo = "007.5";
$foo + 0.5;
ok($foo eq '007.5', "after being treated as a float it still has its original value");
is(type($foo), 'SCALAR', "and it's not become a float as far as we're concerned");
note(capture_stderr { Dump($foo) });
};

subtest "'7'" => sub {
my $foo = '7';
$foo < 8;
is(type($foo), 'INTEGER', "this does become an int after a numeric operation");
note(capture_stderr { Dump($foo) });
};
};

subtest "int subsequently used as a float" => sub {
my $foo = 7;
$foo + 0.5;
ok($foo == 7, "after being treated as a float the variable still has its original value 7");
ok(is_integer($foo), "7 is still an integer after being numerically compared to a float");
};

subtest "are we checking the flags, not just the contents of the IV/NV slots?" => sub {
my $foo = 42;
ok(is_integer($foo), 'variable containing 42 is an integer');
Expand Down
10 changes: 10 additions & 0 deletions t/pod-coverage.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use strict;
use warnings;

use Test::More;
eval "use Test::Pod::Coverage 1.08";
plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage" if $@;
foreach my $module (grep { $_ !~ m{\b(UK::Exchanges|Data|StubCountry(::..)?)$} } all_modules()) {
pod_coverage_ok($module);
}
done_testing();
8 changes: 8 additions & 0 deletions t/pod.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use strict;
use warnings;

use Test::More;
eval "use Test::Pod 1.18";
plan skip_all => "Test::Pod 1.18 required for testing POD" if $@;
all_pod_files_ok(grep { $_ !~ m{Number/Phone/UK/Data.pm$} } all_pod_files());
done_testing();

0 comments on commit 35c9ac0

Please sign in to comment.