| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Evo::Class::Meta; | 
| 2 | 41 |  |  | 41 |  | 22479 | use Evo 'Carp croak; Scalar::Util reftype; -Internal::Util; Module::Load ()'; | 
|  | 41 |  |  |  |  | 101 |  | 
|  | 41 |  |  |  |  | 246 |  | 
| 3 | 41 |  |  | 41 |  | 286 | use Evo '/::Attrs *; /::Syntax *'; | 
|  | 41 |  |  |  |  | 92 |  | 
|  | 41 |  |  |  |  | 174 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | our @CARP_NOT = qw(Evo::Class); | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 203 | 50 |  | 203 | 1 | 1271 | sub register ($me, $package) { | 
|  | 203 | 50 |  |  |  | 606 |  | 
|  | 203 |  |  |  |  | 450 |  | 
|  | 203 |  |  |  |  | 358 |  | 
|  | 203 |  |  |  |  | 348 |  | 
| 8 | 41 |  |  | 41 |  | 320 | no strict 'refs';    ## no critic | 
|  | 41 |  |  |  |  | 92 |  | 
|  | 41 |  |  |  |  | 1426 |  | 
| 9 | 41 |  |  | 41 |  | 209 | no warnings 'once'; | 
|  | 41 |  |  |  |  | 90 |  | 
|  | 41 |  |  |  |  | 5952 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 203 |  | 66 |  |  | 349 | ${"${package}::EVO_CLASS_ATTRS"} ||= Evo::Class::Attrs->new; | 
|  | 203 |  |  |  |  | 2562 |  | 
| 12 |  |  |  |  |  |  |  | 
| 13 | 203 |  | 100 |  |  | 374 | ${"${package}::EVO_CLASS_META"} | 
|  | 203 |  |  |  |  | 2495 |  | 
| 14 |  |  |  |  |  |  | ||= bless {package => $package, private => {}, methods => {}, reqs => {}, overridden => {}}, | 
| 15 |  |  |  |  |  |  | $me; | 
| 16 |  |  |  |  |  |  | } | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 516 | 50 |  | 516 | 0 | 1428 | sub find_or_croak ($self, $package) { | 
|  | 516 | 50 |  |  |  | 1341 |  | 
|  | 516 |  |  |  |  | 957 |  | 
|  | 516 |  |  |  |  | 878 |  | 
|  | 516 |  |  |  |  | 770 |  | 
| 19 | 41 |  |  | 41 |  | 305 | no strict 'refs';    ## no critic | 
|  | 41 |  |  |  |  | 91 |  | 
|  | 41 |  |  |  |  | 6516 |  | 
| 20 | 516 | 100 |  |  |  | 776 | ${"${package}::EVO_CLASS_META"} | 
|  | 516 |  |  |  |  | 3418 |  | 
| 21 |  |  |  |  |  |  | or croak qq#$package isn't Evo::Class; "use parent '$package';" for external classes#; | 
| 22 |  |  |  |  |  |  | } | 
| 23 |  |  |  |  |  |  |  | 
| 24 | 4344 | 50 |  | 4344 | 0 | 9312 | sub package($self) { $self->{package} } | 
|  | 4344 | 50 |  |  |  | 8827 |  | 
|  | 4344 |  |  |  |  | 6306 |  | 
|  | 4344 |  |  |  |  | 6213 |  | 
|  | 4344 |  |  |  |  | 8258 |  | 
| 25 |  |  |  |  |  |  |  | 
| 26 | 1862 | 50 |  | 1862 | 1 | 6482 | sub attrs($self) { | 
|  | 1862 | 50 |  |  |  | 3984 |  | 
|  | 1862 |  |  |  |  | 2870 |  | 
|  | 1862 |  |  |  |  | 2560 |  | 
| 27 | 41 |  |  | 41 |  | 253 | no strict 'refs';    ## no critic | 
|  | 41 |  |  |  |  | 146 |  | 
|  | 41 |  |  |  |  | 18765 |  | 
| 28 | 1862 |  |  |  |  | 3116 | my $package = $self->{package}; | 
| 29 | 1862 |  |  |  |  | 2569 | ${"${package}::EVO_CLASS_ATTRS"}; | 
|  | 1862 |  |  |  |  | 13925 |  | 
| 30 |  |  |  |  |  |  | } | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 2789 | 50 |  | 2789 | 0 | 5951 | sub methods($self) { $self->{methods} } | 
|  | 2789 | 50 |  |  |  | 5620 |  | 
|  | 2789 |  |  |  |  | 4045 |  | 
|  | 2789 |  |  |  |  | 3913 |  | 
|  | 2789 |  |  |  |  | 6965 |  | 
| 33 | 89 | 50 |  | 89 | 0 | 251 | sub reqs($self)    { $self->{reqs} } | 
|  | 89 | 50 |  |  |  | 237 |  | 
|  | 89 |  |  |  |  | 157 |  | 
|  | 89 |  |  |  |  | 153 |  | 
|  | 89 |  |  |  |  | 389 |  | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 331 | 50 |  | 331 | 1 | 824 | sub overridden($self) { $self->{overridden} } | 
|  | 331 | 50 |  |  |  | 733 |  | 
|  | 331 |  |  |  |  | 542 |  | 
|  | 331 |  |  |  |  | 521 |  | 
|  | 331 |  |  |  |  | 1007 |  | 
| 36 | 1862 | 50 |  | 1862 | 1 | 3942 | sub private($self)    { $self->{private} } | 
|  | 1862 | 50 |  |  |  | 3689 |  | 
|  | 1862 |  |  |  |  | 2681 |  | 
|  | 1862 |  |  |  |  | 2480 |  | 
|  | 1862 |  |  |  |  | 6044 |  | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 16 | 50 |  | 16 | 0 | 1245 | sub mark_as_overridden ($self, $name) { | 
|  | 16 | 50 |  |  |  | 39 |  | 
|  | 16 |  |  |  |  | 27 |  | 
|  | 16 |  |  |  |  | 24 |  | 
|  | 16 |  |  |  |  | 27 |  | 
| 39 | 16 |  |  |  |  | 36 | $self->overridden->{$name} = 1; | 
| 40 | 16 |  |  |  |  | 33 | $self; | 
| 41 |  |  |  |  |  |  | } | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 314 | 50 |  | 314 | 0 | 860 | sub is_overridden ($self, $name) { | 
|  | 314 | 50 |  |  |  | 729 |  | 
|  | 314 |  |  |  |  | 523 |  | 
|  | 314 |  |  |  |  | 529 |  | 
|  | 314 |  |  |  |  | 466 |  | 
| 44 | 314 |  |  |  |  | 700 | $self->overridden->{$name}; | 
| 45 |  |  |  |  |  |  | } | 
| 46 |  |  |  |  |  |  |  | 
| 47 | 15 | 50 |  | 15 | 1 | 796 | sub mark_as_private ($self, $name) { | 
|  | 15 | 50 |  |  |  | 37 |  | 
|  | 15 |  |  |  |  | 25 |  | 
|  | 15 |  |  |  |  | 29 |  | 
|  | 15 |  |  |  |  | 27 |  | 
| 48 | 15 |  |  |  |  | 45 | $self->private->{$name} = 1; | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 1846 | 50 |  | 1846 | 0 | 3975 | sub is_private ($self, $name) { | 
|  | 1846 | 50 |  |  |  | 3716 |  | 
|  | 1846 |  |  |  |  | 2682 |  | 
|  | 1846 |  |  |  |  | 2705 |  | 
|  | 1846 |  |  |  |  | 2495 |  | 
| 52 | 1846 |  |  |  |  | 3371 | $self->private->{$name}; | 
| 53 |  |  |  |  |  |  | } | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | # first check methods (marked as method or inherited), if doesn't exists, try to determine if there is a sub in package | 
| 56 |  |  |  |  |  |  | # if a sub is compiled in the same package, it's a public, if not(imported or xsub), and not exported function - it's private | 
| 57 |  |  |  |  |  |  |  | 
| 58 | 2573 | 50 |  | 2573 | 0 | 6660 | sub is_method ($self, $name) { | 
|  | 2573 | 50 |  |  |  | 5349 |  | 
|  | 2573 |  |  |  |  | 3796 |  | 
|  | 2573 |  |  |  |  | 3806 |  | 
|  | 2573 |  |  |  |  | 3499 |  | 
| 59 | 2573 | 100 |  |  |  | 4997 | return 1 if $self->methods->{$name}; | 
| 60 | 2547 |  |  |  |  | 4931 | my $pkg = $self->package; | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | { | 
| 63 | 41 |  |  | 41 |  | 276 | no strict 'refs';    ## no critic | 
|  | 41 |  |  |  |  | 98 |  | 
|  | 41 |  |  |  |  | 1452 |  | 
|  | 2547 |  |  |  |  | 3967 |  | 
| 64 | 41 |  |  | 41 |  | 200 | no warnings 'once'; | 
|  | 41 |  |  |  |  | 89 |  | 
|  | 41 |  |  |  |  | 54625 |  | 
| 65 | 2547 |  |  |  |  | 3527 | my $meta = ${"${pkg}::EVO_EXPORT_META"}; | 
|  | 2547 |  |  |  |  | 6638 |  | 
| 66 | 2547 | 100 | 100 |  |  | 5929 | return if $meta && $meta->symbols->{$name}; | 
| 67 |  |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  |  | 
| 69 | 2545 | 100 |  |  |  | 6247 | my $code = Evo::Internal::Util::names2code($pkg, $name) or return; | 
| 70 | 1491 |  |  |  |  | 3682 | my ($realpkg, $realname, $xsub) = Evo::Internal::Util::code2names($code); | 
| 71 | 1491 |  | 100 |  |  | 8937 | return !$xsub && $realpkg eq $pkg; | 
| 72 |  |  |  |  |  |  | } | 
| 73 |  |  |  |  |  |  |  | 
| 74 | 1234 | 50 |  | 1234 | 0 | 4506 | sub is_attr ($self, $name) { | 
|  | 1234 | 50 |  |  |  | 2749 |  | 
|  | 1234 |  |  |  |  | 1853 |  | 
|  | 1234 |  |  |  |  | 1870 |  | 
|  | 1234 |  |  |  |  | 1714 |  | 
| 75 | 1234 |  |  |  |  | 2494 | $self->attrs->exists($name); | 
| 76 |  |  |  |  |  |  | } | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 722 | 50 |  | 722 |  | 1688 | sub _check_valid_name ($self, $name) { | 
|  | 722 | 50 |  |  |  | 1610 |  | 
|  | 722 |  |  |  |  | 1153 |  | 
|  | 722 |  |  |  |  | 1117 |  | 
|  | 722 |  |  |  |  | 1036 |  | 
| 79 | 722 | 100 |  |  |  | 1990 | croak(qq{"$name" is invalid name}) unless Evo::Internal::Util::check_subname($name); | 
| 80 |  |  |  |  |  |  | } | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 920 | 50 |  | 920 |  | 2208 | sub _check_exists ($self, $name) { | 
|  | 920 | 50 |  |  |  | 2074 |  | 
|  | 920 |  |  |  |  | 1462 |  | 
|  | 920 |  |  |  |  | 1429 |  | 
|  | 920 |  |  |  |  | 1367 |  | 
| 83 | 920 |  |  |  |  | 2095 | my $pkg = $self->package; | 
| 84 | 920 | 100 |  |  |  | 2163 | croak qq{$pkg already has attribute "$name"} if $self->is_attr($name); | 
| 85 | 915 | 100 |  |  |  | 2429 | croak qq{$pkg already has method "$name"}    if $self->is_method($name); | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  |  | 
| 88 | 714 | 50 |  | 714 |  | 1782 | sub _check_exists_valid_name ($self, $name) { | 
|  | 714 | 50 |  |  |  | 1640 |  | 
|  | 714 |  |  |  |  | 1155 |  | 
|  | 714 |  |  |  |  | 1178 |  | 
|  | 714 |  |  |  |  | 1048 |  | 
| 89 | 714 |  |  |  |  | 1807 | _check_valid_name($self, $name); | 
| 90 | 712 |  |  |  |  | 1841 | _check_exists($self, $name); | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  |  | 
| 93 | 493 | 50 |  | 493 |  | 1299 | sub _reg_parsed_attr ($self, %opts) { | 
|  | 493 | 50 |  |  |  | 1253 |  | 
|  | 493 |  |  |  |  | 827 |  | 
|  | 493 |  |  |  |  | 2187 |  | 
|  | 493 |  |  |  |  | 990 |  | 
| 94 | 493 |  |  |  |  | 881 | my $name = $opts{name}; | 
| 95 | 493 |  |  |  |  | 1325 | _check_exists_valid_name($self, $name); | 
| 96 | 487 |  |  |  |  | 1144 | my $pkg = $self->package; | 
| 97 | 487 | 100 |  |  |  | 1274 | croak qq{$pkg already has subroutine "$name"} if Evo::Internal::Util::names2code($pkg, $name); | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 484 |  |  |  |  | 1146 | my $sub = $self->attrs->gen_attr(%opts);    # register | 
| 100 | 484 | 100 |  |  |  | 2393 | Evo::Internal::Util::monkey_patch $pkg, $name, $sub if $opts{method}; | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  |  | 
| 103 | 8 | 50 |  | 8 |  | 26 | sub _reg_parsed_attr_over ($self, %opts) { | 
|  | 8 | 50 |  |  |  | 28 |  | 
|  | 8 |  |  |  |  | 15 |  | 
|  | 8 |  |  |  |  | 36 |  | 
|  | 8 |  |  |  |  | 16 |  | 
| 104 | 8 |  |  |  |  | 19 | my $name = $opts{name}; | 
| 105 | 8 |  |  |  |  | 20 | _check_valid_name($self, $name); | 
| 106 | 8 |  |  |  |  | 27 | $self->mark_as_overridden($name); | 
| 107 | 8 |  |  |  |  | 18 | my $sub = $self->attrs->gen_attr(%opts);    # register | 
| 108 | 8 |  |  |  |  | 41 | my $pkg = $self->package; | 
| 109 | 8 | 100 |  |  |  | 42 | Evo::Internal::Util::monkey_patch_silent $pkg, $name, $sub if $opts{method}; | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 403 | 50 |  | 403 | 0 | 1332 | sub reg_attr ($self, $name, @attr) { | 
|  | 403 |  |  |  |  | 674 |  | 
|  | 403 |  |  |  |  | 652 |  | 
|  | 403 |  |  |  |  | 1018 |  | 
|  | 403 |  |  |  |  | 702 |  | 
| 113 | 403 |  |  |  |  | 1369 | my %opts = $self->parse_attr($name, @attr); | 
| 114 | 403 |  |  |  |  | 1631 | $self->_reg_parsed_attr(%opts); | 
| 115 |  |  |  |  |  |  | } | 
| 116 |  |  |  |  |  |  |  | 
| 117 | 8 | 50 |  | 8 | 0 | 23 | sub reg_attr_over ($self, $name, @attr) { | 
|  | 8 |  |  |  |  | 16 |  | 
|  | 8 |  |  |  |  | 13 |  | 
|  | 8 |  |  |  |  | 21 |  | 
|  | 8 |  |  |  |  | 15 |  | 
| 118 | 8 |  |  |  |  | 21 | my %opts = $self->parse_attr($name, @attr); | 
| 119 | 8 |  |  |  |  | 38 | $self->_reg_parsed_attr_over(%opts); | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | # means register external sub as method. Because every sub in the current package | 
| 123 |  |  |  |  |  |  | # is public by default | 
| 124 | 221 | 50 |  | 221 | 1 | 757 | sub reg_method ($self, $name) { | 
|  | 221 | 50 |  |  |  | 536 |  | 
|  | 221 |  |  |  |  | 481 |  | 
|  | 221 |  |  |  |  | 369 |  | 
|  | 221 |  |  |  |  | 347 |  | 
| 125 | 221 |  |  |  |  | 555 | _check_exists_valid_name($self, $name); | 
| 126 | 217 |  |  |  |  | 574 | my $pkg = $self->package; | 
| 127 | 217 | 100 |  |  |  | 568 | my $code = Evo::Internal::Util::names2code($pkg, $name) or croak "$pkg::$name doesn't exist"; | 
| 128 | 215 |  |  |  |  | 536 | $self->methods->{$name}++; | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 57 | 50 |  | 57 |  | 205 | sub _public_attrs_slots($self) { | 
|  | 57 | 50 |  |  |  | 157 |  | 
|  | 57 |  |  |  |  | 105 |  | 
|  | 57 |  |  |  |  | 101 |  | 
| 132 | 57 |  |  |  |  | 180 | grep { !$self->is_private($_->{name}) } $self->attrs->slots; | 
|  | 188 |  |  |  |  | 484 |  | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | # not marked as private | 
| 136 |  |  |  |  |  |  | # was compiled in the same package, not constant, not exported lib | 
| 137 | 61 | 50 |  | 61 |  | 192 | sub _public_methods_map($self) { | 
|  | 61 | 50 |  |  |  | 166 |  | 
|  | 61 |  |  |  |  | 112 |  | 
|  | 61 |  |  |  |  | 119 |  | 
| 138 | 61 |  |  |  |  | 145 | my $pkg = $self->package; | 
| 139 | 435 |  |  |  |  | 1009 | map { ($_, Evo::Internal::Util::names2code($pkg, $_)) } | 
| 140 | 61 | 100 |  |  |  | 230 | grep { !$self->is_private($_) && $self->is_method($_) } | 
|  | 1656 |  |  |  |  | 3568 |  | 
| 141 |  |  |  |  |  |  | Evo::Internal::Util::list_symbols($pkg); | 
| 142 |  |  |  |  |  |  | } | 
| 143 |  |  |  |  |  |  |  | 
| 144 | 26 | 50 |  | 26 | 0 | 1153 | sub public_attrs($self) { | 
|  | 26 | 50 |  |  |  | 77 |  | 
|  | 26 |  |  |  |  | 52 |  | 
|  | 26 |  |  |  |  | 47 |  | 
| 145 | 26 |  |  |  |  | 80 | map { $_->{name} } $self->_public_attrs_slots; | 
|  | 92 |  |  |  |  | 261 |  | 
| 146 |  |  |  |  |  |  | } | 
| 147 |  |  |  |  |  |  |  | 
| 148 | 27 | 50 |  | 27 | 0 | 98 | sub public_methods($self) { | 
|  | 27 | 50 |  |  |  | 91 |  | 
|  | 27 |  |  |  |  | 50 |  | 
|  | 27 |  |  |  |  | 47 |  | 
| 149 | 27 |  |  |  |  | 90 | my %map = $self->_public_methods_map; | 
| 150 | 27 |  |  |  |  | 459 | keys %map; | 
| 151 |  |  |  |  |  |  | } | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  |  | 
| 154 | 32 | 50 |  | 32 | 0 | 143 | sub extend_with ($self, $source_p) { | 
|  | 32 | 50 |  |  |  | 98 |  | 
|  | 32 |  |  |  |  | 57 |  | 
|  | 32 |  |  |  |  | 62 |  | 
|  | 32 |  |  |  |  | 55 |  | 
| 155 | 32 |  |  |  |  | 95 | $source_p = Evo::Internal::Util::resolve_package($self->package, $source_p); | 
| 156 | 32 |  |  |  |  | 163 | Module::Load::load($source_p); | 
| 157 | 32 |  |  |  |  | 566 | my $source  = $self->find_or_croak($source_p); | 
| 158 | 31 |  |  |  |  | 90 | my $dest_p  = $self->package; | 
| 159 | 31 |  |  |  |  | 89 | my %reqs    = $source->reqs()->%*; | 
| 160 | 31 |  |  |  |  | 109 | my %methods = $source->_public_methods_map(); | 
| 161 |  |  |  |  |  |  |  | 
| 162 | 31 |  |  |  |  | 109 | my @new_attrs; | 
| 163 | 31 |  |  |  |  | 113 | foreach my $name (keys %reqs) { $self->reg_requirement($name); } | 
|  | 14 |  |  |  |  | 85 |  | 
| 164 |  |  |  |  |  |  |  | 
| 165 | 31 |  |  |  |  | 120 | foreach my $slot ($source->_public_attrs_slots) { | 
| 166 | 93 | 100 |  |  |  | 299 | next if $self->is_overridden($slot->{name}); | 
| 167 | 90 |  |  |  |  | 439 | $self->_reg_parsed_attr(%$slot); | 
| 168 | 87 |  |  |  |  | 317 | push @new_attrs, $slot->{name}; | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  |  | 
| 171 | 28 |  |  |  |  | 212 | foreach my $name (keys %methods) { | 
| 172 | 215 | 100 |  |  |  | 532 | next if $self->is_overridden($name); | 
| 173 | 211 | 100 |  |  |  | 598 | croak qq/$dest_p already has a subroutine with name "$name"/ | 
| 174 |  |  |  |  |  |  | if Evo::Internal::Util::names2code($dest_p, $name); | 
| 175 | 208 |  |  |  |  | 604 | _check_exists($self, $name);    # prevent patching before check | 
| 176 | 208 |  |  |  |  | 725 | Evo::Internal::Util::monkey_patch $dest_p, $name, $methods{$name}; | 
| 177 | 208 |  |  |  |  | 673 | $self->reg_method($name); | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 41 |  |  | 41 |  | 339 | no strict 'refs';                 ## no critic | 
|  | 41 |  |  |  |  | 91 |  | 
|  | 41 |  |  |  |  | 30119 |  | 
| 181 | 25 |  |  |  |  | 72 | push @{"${dest_p}::ISA"}, $source_p; | 
|  | 25 |  |  |  |  | 426 |  | 
| 182 | 25 |  |  |  |  | 182 | @new_attrs; | 
| 183 |  |  |  |  |  |  | } | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  |  | 
| 186 | 33 | 50 |  | 33 | 0 | 345 | sub reg_requirement ($self, $name) { | 
|  | 33 | 50 |  |  |  | 116 |  | 
|  | 33 |  |  |  |  | 71 |  | 
|  | 33 |  |  |  |  | 71 |  | 
|  | 33 |  |  |  |  | 65 |  | 
| 187 | 33 |  |  |  |  | 124 | $self->reqs->{$name}++; | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  |  | 
| 190 | 23 | 50 |  | 23 | 0 | 87 | sub requirements($self) { | 
|  | 23 | 50 |  |  |  | 88 |  | 
|  | 23 |  |  |  |  | 55 |  | 
|  | 23 |  |  |  |  | 124 |  | 
| 191 | 23 |  |  |  |  | 121 | (keys($self->reqs->%*), $self->public_attrs, $self->public_methods); | 
| 192 |  |  |  |  |  |  | } | 
| 193 |  |  |  |  |  |  |  | 
| 194 | 20 | 50 |  | 20 | 1 | 111 | sub check_implementation ($self, $inter_class) { | 
|  | 20 | 50 |  |  |  | 84 |  | 
|  | 20 |  |  |  |  | 48 |  | 
|  | 20 |  |  |  |  | 51 |  | 
|  | 20 |  |  |  |  | 43 |  | 
| 195 | 20 |  |  |  |  | 74 | $inter_class = Evo::Internal::Util::resolve_package($self->package, $inter_class); | 
| 196 | 20 |  |  |  |  | 126 | Module::Load::load($inter_class); | 
| 197 | 20 |  |  |  |  | 1802 | my $class = $self->package; | 
| 198 | 20 |  |  |  |  | 186 | my $inter = $self->find_or_croak($inter_class); | 
| 199 | 19 |  |  |  |  | 90 | my @reqs  = sort $inter->requirements; | 
| 200 |  |  |  |  |  |  |  | 
| 201 | 19 |  | 100 |  |  | 81 | my @not_exists = grep { !($self->is_attr($_) || $class->can($_)); } @reqs; | 
|  | 305 |  |  |  |  | 656 |  | 
| 202 | 19 | 100 |  |  |  | 189 | return $self if !@not_exists; | 
| 203 |  |  |  |  |  |  |  | 
| 204 | 3 |  |  |  |  | 306 | croak qq/Bad implementation of "$inter_class", missing in "$class": /, join ';', @not_exists; | 
| 205 |  |  |  |  |  |  | } | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | # -- class methods for usage from other modules too | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  | # rtype: default, default_code, required, lazy, relaxed | 
| 211 |  |  |  |  |  |  | # rvalue is used as meta for required(di), default and lazy | 
| 212 |  |  |  |  |  |  | # check? | 
| 213 |  |  |  |  |  |  | # is_ro? | 
| 214 |  |  |  |  |  |  |  | 
| 215 | 449 | 50 |  | 449 | 0 | 1820 | sub parse_attr ($me, $name, @attr) { | 
|  | 449 |  |  |  |  | 738 |  | 
|  | 449 |  |  |  |  | 703 |  | 
|  | 449 |  |  |  |  | 978 |  | 
|  | 449 |  |  |  |  | 740 |  | 
| 216 | 449 |  |  |  |  | 823 | my @scalars = grep { $_ ne SYNTAX_STATE } @attr; | 
|  | 339 |  |  |  |  | 1371 |  | 
| 217 | 449 | 100 |  |  |  | 1552 | croak "expected 1 scalar, got: " . join ',', @scalars if @scalars > 1; | 
| 218 | 448 |  |  |  |  | 1316 | my %state = syntax_reset; | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | croak qq#"optional" flag makes no sense with default("$scalars[0]")# | 
| 221 | 448 | 100 | 100 |  |  | 1864 | if $state{optional} && @scalars; | 
| 222 |  |  |  |  |  |  | croak qq#"lazy" requires code reference# | 
| 223 | 447 | 100 | 100 |  |  | 1651 | if $state{lazy} && (reftype($scalars[0]) // '') ne 'CODE'; | 
|  |  |  | 100 |  |  |  |  | 
| 224 | 444 | 100 | 100 |  |  | 1951 | croak qq#default("$scalars[0]") should be either a scalar or a code reference# | 
|  |  |  | 100 |  |  |  |  | 
| 225 |  |  |  |  |  |  | if @scalars && ref($scalars[0]) && reftype($scalars[0]) ne 'CODE'; | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  |  | 
| 228 | 443 |  |  |  |  | 719 | my $type; | 
| 229 | 443 | 50 |  |  |  | 1426 | if    ($state{optional}) { $type = ECA_OPTIONAL if $state{optional}; } | 
|  | 141 | 100 |  |  |  | 408 |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 230 | 14 | 50 |  |  |  | 40 | elsif ($state{lazy})     { $type = ECA_LAZY     if $state{lazy}; } | 
| 231 | 66 | 100 |  |  |  | 251 | elsif (@scalars) { $type = ref($scalars[0]) ? ECA_DEFAULT_CODE : ECA_DEFAULT; } | 
| 232 | 222 |  |  |  |  | 374 | else             { $type = ECA_REQUIRED; } | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | return ( | 
| 235 |  |  |  |  |  |  | name   => $name, | 
| 236 |  |  |  |  |  |  | type   => $type, | 
| 237 |  |  |  |  |  |  | value  => $scalars[0], | 
| 238 |  |  |  |  |  |  | check  => $state{check}, | 
| 239 |  |  |  |  |  |  | ro     => !!$state{ro}, | 
| 240 |  |  |  |  |  |  | inject => $state{inject}, | 
| 241 |  |  |  |  |  |  | method => !$state{no_method}, | 
| 242 | 443 |  |  |  |  | 3094 | ); | 
| 243 |  |  |  |  |  |  | } | 
| 244 |  |  |  |  |  |  |  | 
| 245 | 1 | 50 |  | 1 | 0 | 10 | sub info($self) { | 
|  | 1 | 50 |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2 |  | 
| 246 | 1 |  |  |  |  | 4 | my %info = ( | 
| 247 |  |  |  |  |  |  | public => { | 
| 248 |  |  |  |  |  |  | methods => [sort $self->public_methods], | 
| 249 |  |  |  |  |  |  | attrs   => [sort $self->public_attrs], | 
| 250 |  |  |  |  |  |  | reqs    => [sort keys($self->reqs->%*)], | 
| 251 |  |  |  |  |  |  | }, | 
| 252 |  |  |  |  |  |  | overridden => [sort keys($self->overridden->%*)], | 
| 253 |  |  |  |  |  |  | private    => [sort keys($self->private->%*)], | 
| 254 |  |  |  |  |  |  | ); | 
| 255 | 1 |  |  |  |  | 16 | \%info; | 
| 256 |  |  |  |  |  |  | } | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  |  | 
| 259 |  |  |  |  |  |  | 1; | 
| 260 |  |  |  |  |  |  |  | 
| 261 |  |  |  |  |  |  | __END__ |