Skip to content

Commit

Permalink
add BOOL type; add is_bool function
Browse files Browse the repository at this point in the history
  • Loading branch information
DrHyde committed Jan 6, 2022
1 parent e41d321 commit a27419b
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
@@ -1,3 +1,7 @@
X.X.X XXXX-XX-XX

- add support for BOOL type on perl 5.35.7 and later

0.2.0 2021-11-08

- add sizeof() function for numeric types
Expand Down
1 change: 1 addition & 0 deletions MANIFEST
Expand Up @@ -11,3 +11,4 @@ MANIFEST.SKIP
t/pod-coverage.t
t/pod.t
t/sizeof.t
t/bool.t
1 change: 1 addition & 0 deletions Makefile.PL
Expand Up @@ -19,5 +19,6 @@ WriteMakefile(
'Devel::Peek' => 0,
'Capture::Tiny' => 0,
'Carp' => 0,
'if' => 0,
},
);
61 changes: 50 additions & 11 deletions lib/Scalar/Type.pm
Expand Up @@ -3,6 +3,12 @@ package Scalar::Type;
use strict;
use warnings;

our $BOOL_SUPPORTED;

BEGIN { $BOOL_SUPPORTED = ($] >= 5.035007) }

use if $BOOL_SUPPORTED, qw(builtin isbool);

use Carp qw(croak);
use Config;

Expand Down Expand Up @@ -63,7 +69,7 @@ For Reasons, C<:is_*> is equivalent.
=cut

our @EXPORT_OK = qw(
type sizeof is_integer is_number
type sizeof is_integer is_number is_bool
);
our %EXPORT_TAGS = (
all => \@EXPORT_OK,
Expand All @@ -81,22 +87,31 @@ them without.
=head2 type
Returns the type of its argument. If the argument is a reference then it
returns either C<blessed($argument)> (if it's an object),
C<'REF_TO_'.ref($argument)>, or C<'UNDEF'> for undefined values. Otherwise it
looks for the IOK or NOK flags on the underlying SV (see <L/"GORY DETAILS"> for
the exact mechanics) and returns C<INTEGER> or C<NUMBER> as appropriate.
Finally, if neither of those are set it returns C<SCALAR>.
Returns the type of its argument.
If the argument is a reference then it returns either
C<blessed($argument)> (if it's an object),
or C<'REF_TO_'.ref($argument)>.
If the argument is C<undef> then it returns C<'UNDEF'>.
If you are using perl 5.35.7 or later and the argument is the result of a
comparison then it returns C<'BOOL'>.
Otherwise it looks for the IOK or NOK flags on the underlying SV (see
L</"GORY DETAILS"> for the exact mechanics) and returns C<INTEGER> or C<NUMBER>
as appropriate. Finally, if neither of those are set it returns C<SCALAR>.
=cut

sub type {
croak(__PACKAGE__."::type requires an argument") if($#_ == -1);
my $arg = shift;
return blessed($arg) ? blessed($arg) :
ref($arg) ? 'REF_TO_'.ref($arg) :
!defined($arg) ? 'UNDEF' :
_scalar_type($arg);
return blessed($arg) ? blessed($arg) :
ref($arg) ? 'REF_TO_'.ref($arg) :
!defined($arg) ? 'UNDEF' :
($BOOL_SUPPORTED && isbool($arg)) ? 'BOOL' :
_scalar_type($arg);
}

=head2 sizeof
Expand Down Expand Up @@ -146,6 +161,20 @@ sub is_number {
is_integer(@_) || type(@_) eq 'NUMBER' ? 1 : 0;
}

=head2 is_bool
It is a fatal error to call this on perl versions earlier than 5.35.7.
Returns true if its argument is a Boolean - ie, the result of a comparison.
=cut

sub is_bool {
croak(__PACKAGE__."::is_bool not supported on your perl") if(!$BOOL_SUPPORTED);
croak(__PACKAGE__."::is_bool requires an argument") if($#_ == -1);
type(@_) eq 'BOOL';
}

=head1 GORY DETAILS
=head2 PERL VARIABLE INTERNALS
Expand Down Expand Up @@ -259,6 +288,14 @@ slot to be filled, and the C<IOK> flag set. It should, of course, be clear
to any fan of classic literature that "007" and 7 are very different things.
"007" is not an integer.
=head3 Booleans
In perl 5.35.7 and later, Boolean values - ie the results of comparisons -
have some extra magic. As well as their value, which is either C<1> (true,
an integer) or C<''> (false, an empty string), they have a flag to indicate
their Booleanness. This is exposed via the C<builtin::isbool> perl function
so we don't need to do XS voodoo to interrogate it.
=head2 WHAT Scalar::Type DOES (at least in version 0.1.0)
NB that this section documents an internal function that is not intended
Expand Down Expand Up @@ -300,6 +337,8 @@ the number.
L<Scalar::Util> in particular its C<blessed> function.
L<builtin> if you have perl 5.35.7 or later.
=head1 BUGS
If you find any bugs please report them on Github, preferably with a test case.
Expand Down
44 changes: 44 additions & 0 deletions t/bool.t
@@ -0,0 +1,44 @@
use strict;
use warnings;

use Test::More;
use Test::Exception;

use Config;

use Scalar::Type qw(:all);

if($Scalar::Type::BOOL_SUPPORTED) {
is(
type(1 == 1),
'BOOL',
'type(1 == 1) is BOOL'
);
is(
type(1 == 0),
'BOOL',
'type(1 == 0) is BOOL'
);
ok(is_bool(1 == 1), 'is_bool says yes for (1 == 1)');
ok(is_bool(1 == 0), 'is_bool says yes for (1 == 0)');
ok(!is_bool(1), 'but it says no for plain old 1 (otherwise indistinguishable from (1 == 1))');
ok(!is_bool(''), "and it says no for plain old '' (otherwise indistinguishable from (1 == 0))");
} else {
throws_ok(
sub { is_bool(1 == 1) },
qr/::is_bool not supported on your perl/,
"is_bool carks it on Ye Olde Perle $]"
);
is(
type(1 == 1),
'INTEGER',
'type(1 == 1) is INTEGER'
);
is(
type(1 == 0),
'SCALAR',
'type(1 == 0) is SCALAR'
);
}

done_testing;

0 comments on commit a27419b

Please sign in to comment.