Aion
view release on metacpan or search on metacpan
lib/Aion/Types.pm view on Meta::CPAN
package Aion::Types;
# ТипÑ-валидаÑоÑÑ Ð´Ð»Ñ Aion
use common::sense;
use Aion::Meta::Util qw/subref_is_reachable/;
use Aion::Type;
use List::Util qw/all any first/;
use Exporter qw/import/;
require overload;
use Scalar::Util qw/looks_like_number reftype refaddr blessed/;
use Sub::Util qw//;
our @EXPORT = our @EXPORT_OK = grep {
*{$Aion::Types::{$_}}{CODE} && !/^(_|(NaN|import|all|any|first|looks_like_number|reftype|refaddr|blessed|subref_is_reachable)\z)/n
} keys %Aion::Types::;
# ÐбÑабаÑÑваем аÑÑибÑÑ :Isa
sub MODIFY_CODE_ATTRIBUTES {
my ($pkg, $referent, @attributes) = @_;
grep { /^Isa\((.*)\)\z/s? do { _Isa($pkg, $referent, $1); 0 }: 1 } @attributes
}
sub _Isa {
my ($pkg, $referent, $data) = @_;
my $subname = Sub::Util::subname $referent;
$subname =~ s/^.*:://;
die "Anonymous subroutine cannot use :Isa!" if $subname eq '__ANON__';
my @signature = eval "package $pkg; map { UNIVERSAL::isa(\$_, 'Aion::Type')? \$_: __PACKAGE__->can(\$_)? __PACKAGE__->can(\$_)->(): Aion::Types::External([\$_]) } ($data)";
die if $@;
die "$pkg\::$subname has no return type!" if @signature == 0;
require Aion::Meta::Subroutine;
my $subroutine = Aion::Meta::Subroutine->new(
pkg => $pkg,
subname => $subname,
signature => \@signature,
referent => $referent,
);
if(!subref_is_reachable($referent)) {
$Aion::META{$pkg}{require}{$subname} = $subroutine;
} else {
my $require = delete $Aion::META{$pkg}{require}{$subname};
$require->compare($subroutine) if $require;
my $overload = $Aion::META{$pkg}{subroutine}{$subname};
$overload->compare($subroutine) if $overload;
$subroutine->wrap_sub;
}
}
BEGIN {
my $TRUE = sub {1};
my $INIT_ARGS = sub { @{&ARGS} = map External([$_]), @{&ARGS} };
my $INIT_KW_ARGS = sub { @{&ARGS} = List::Util::pairmap { $a => External([$b]) } @{&ARGS} };
# Создание Ñипа
sub subtype(@) {
my $subtype = shift;
my %o = @_;
my ($as, $init_where, $where, $awhere, $message) = delete @o{qw/as init_where where awhere message/};
$as = External([$as]) if defined $as;
die "subtype $subtype unused keys left: " . join ", ", keys %o if keys %o;
die "subtype format is Name or Name[args] or Name`[args]" if $subtype !~ /^([A-Z_]\w*)(?:(\`)?\[(.*)\])?$/i;
my ($name, $is_maybe_arg, $is_arg) = ($1, $2, $3);
lib/Aion/Types.pm view on Meta::CPAN
" <html1>" ~~ Html # -> ""
=head2 StrDate
Date in C<yyyy-mm-dd> format.
"2001-01-12" ~~ StrDate # -> 1
"01-01-01" ~~ StrDate # -> ""
=head2 StrDateTime
Date and time in the format C<yyyy-mm-dd HH:MM:SS>.
"2012-12-01 00:00:00" ~~ StrDateTime # -> 1
"2012-12-01 00:00:00 " ~~ StrDateTime # -> ""
=head2 StrMatch[regexp]
Matches a string against a regular expression.
' abc ' ~~ StrMatch[qr/abc/] # -> 1
' abbc ' ~~ StrMatch[qr/abc/] # -> ""
=head2 ClassName
The class name is a package with a C<new> method.
'Aion::Type' ~~ ClassName # -> 1
'Aion::Types' ~~ ClassName # -> ""
=head2 RoleName
The role name is a package without the C<new> method, with C<@ISA>, or with any one method.
package ExRole1 {
sub any_method {}
}
package ExRole2 {
our @ISA = qw/ExRole1/;
}
'ExRole1' ~~ RoleName # -> 1
'ExRole2' ~~ RoleName # -> 1
'Aion::Type' ~~ RoleName # -> ""
'Nouname::Empty::Package' ~~ RoleName # -> ""
=head2 StrRat
String representation of rational numbers.
Since in perl rational numbers are supported using the C<bigrat> pragma, which turns all rational numbers into C<Math::BigRat>, it is used in a ghost to C<Rat>.
"6/7" ~~ StrRat # -> 1
"-6/7" ~~ StrRat # -> 1
"+6/7" ~~ StrRat # -> 1
6 ~~ StrRat # -> 1
"inf" ~~ StrRat # -> 1
"+Inf" ~~ StrRat # -> 1
"NaN" ~~ StrRat # -> 1
"-nan" ~~ StrRat # -> 1
6.5 ~~ StrRat # -> 1
"6.5 " ~~ StrRat # -> ''
=head2 Rat
Rational numbers. Short for C<Object['Math::BigRat']>. Has a ghost.
use Math::BigRat;
use Math::BigFloat;
use Math::BigInt;
"6/7" ~~ Rat # -> ""
Math::BigRat->new("6/7") ~~ Rat # -> 1
=head2 Num
Numbers.
-6.5 ~~ Num # -> 1
6.5e-7 ~~ Num # -> 1
"6.5 " ~~ Num # -> ""
=head2 PositiveNum
Positive numbers.
0 ~~ PositiveNum # -> 1
0.1 ~~ PositiveNum # -> 1
-0.1 ~~ PositiveNum # -> ""
-0 ~~ PositiveNum # -> 1
=head2 Float
A machine floating point number is 4 bytes.
-4.8 ~~ Float # -> 1
-3.402823466E+38 ~~ Float # -> 1
+3.402823466E+38 ~~ Float # -> 1
-3.402823467E+38 ~~ Float # -> ""
=head2 Double
A machine floating point number is 8 bytes.
use Scalar::Util qw//;
-4.8 ~~ Double # -> 1
'-1.7976931348623157e+308' ~~ Double # -> 1
'+1.7976931348623157e+308' ~~ Double # -> 1
'-1.7976931348623159e+308' ~~ Double # -> ""
=head2 Range[from, to]
Numbers between C<from> and C<to>.
1 ~~ Range[1, 3] # -> 1
2.5 ~~ Range[1, 3] # -> 1
3 ~~ Range[1, 3] # -> 1
3.1 ~~ Range[1, 3] # -> ""
( run in 1.606 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )