Mercurial > pub > Impl
comparison lib/IMPL/Object/_Base.pm @ 427:09e0086a82a7 ref20150831 tip
Merge
| author | cin |
|---|---|
| date | Tue, 15 May 2018 00:51:33 +0300 |
| parents | c27434cdd611 |
| children |
comparison
equal
deleted
inserted
replaced
| 426:eed50c01e758 | 427:09e0086a82a7 |
|---|---|
| 5 | 5 |
| 6 sub __construct; | 6 sub __construct; |
| 7 sub __destroy; | 7 sub __destroy; |
| 8 | 8 |
| 9 *__construct = _strap_ctor(__PACKAGE__); | 9 *__construct = _strap_ctor(__PACKAGE__); |
| 10 *__destroy = _strap_dtor(__PACKAGE__); | 10 *__destroy = _strap_dtor(__PACKAGE__); |
| 11 | 11 |
| 12 sub DESTROY { | 12 sub DESTROY { |
| 13 shift->__destroy(); | 13 shift->__destroy(); |
| 14 } | 14 } |
| 15 | 15 |
| 16 sub _strap_ctor { | 16 sub _strap_ctor { |
| 17 my ($class, $ctor) = @_; | 17 my ( $class, $ctor ) = @_; |
| 18 no strict 'refs'; | 18 no strict 'refs'; |
| 19 no warnings 'redefine'; | 19 no warnings 'redefine'; |
| 20 | 20 |
| 21 return sub { | 21 return $ctor |
| 22 my $self = ref shift; | 22 ? sub { |
| 23 my $self = ref $_[0]; | |
| 23 | 24 |
| 24 if ($self ne $class) { | 25 if ( $self ne $class ) { |
| 25 my $t = _get_ctor($self, undef, '@_'); | 26 my $t = _get_ctor( $self, undef, '@_' ); |
| 26 *{"${self}::__construct"} = _strap_ctor($self, $t); | 27 *{"${self}::__construct"} = _strap_ctor( $self, $t ); |
| 28 goto &$t; | |
| 29 } | |
| 30 | |
| 31 goto &$ctor; | |
| 32 } | |
| 33 : sub { | |
| 34 my $self = ref $_[0]; | |
| 35 if ( $self ne $class ) { | |
| 36 my $t = _get_ctor( $self, undef, '@_' ); | |
| 37 *{"${self}::__construct"} = _strap_ctor( $self, $t ); | |
| 27 goto &$t if $t; | 38 goto &$t if $t; |
| 28 } else { | |
| 29 goto &$ctor if $ctor; | |
| 30 } | 39 } |
| 31 }; | 40 }; |
| 32 } | 41 } |
| 33 | 42 |
| 34 sub _strap_dtor { | 43 sub _strap_dtor { |
| 35 my ($class, $dtor) = @_; | 44 my ( $class, $dtor ) = @_; |
| 36 | |
| 37 no strict 'refs'; | 45 no strict 'refs'; |
| 38 no warnings 'redefine'; | 46 no warnings 'redefine'; |
| 39 | 47 |
| 40 return sub { | 48 return $dtor |
| 41 my $self = ref shift; | 49 ? sub { |
| 50 my $self = ref $_[0]; | |
| 42 | 51 |
| 43 if ($self ne $class) { | 52 if ( $self ne $class ) { |
| 44 my $t = _get_dtor($self); | 53 my $t = _get_dtor($self); |
| 45 *{"${self}::__destroy"} = _strap_dtor($self, $t); | 54 *{"${self}::__destroy"} = _strap_dtor( $self, $t ); |
| 46 goto &$t if $t; | 55 goto &$t; |
| 47 } else { | |
| 48 goto &$dtor if $dtor; | |
| 49 } | 56 } |
| 50 }; | 57 |
| 58 goto &$dtor; | |
| 59 } | |
| 60 : sub { | |
| 61 my $self = ref $_[0]; | |
| 62 if ( $self ne $class ) { | |
| 63 my $t = _get_dtor($self); | |
| 64 *{"${self}::__destroy"} = _strap_dtor( $self, $t ); | |
| 65 goto &$t if $t; | |
| 66 } | |
| 67 }; | |
| 51 } | 68 } |
| 52 | 69 |
| 53 sub _get_ctor { | 70 sub _get_ctor { |
| 54 my ($class, $prev, $t) = @_; | 71 my ( $class, $prev, $t ) = @_; |
| 55 no strict 'refs'; | 72 no strict 'refs'; |
| 56 | 73 |
| 57 #say "_get_ctor($class, $prev, $t)"; | 74 #say "_get_ctor($class, $prev, $t)"; |
| 58 | 75 |
| 59 my $isolate = ((not defined($t)) or ($t ne '@_')); | 76 my $isolate = ( ( not defined($t) ) or ( $t ne '@_' ) ); |
| 60 | 77 |
| 61 my $ctor = $isolate ? *{"${class}::CTOR"}{CODE} : _chain_call(*{"${class}::CTOR"}{CODE}, $prev); | 78 my $ctor = |
| 62 | 79 $isolate |
| 63 foreach my $base (@{"${class}::ISA"}) { | 80 ? *{"${class}::CTOR"}{CODE} |
| 64 $ctor = _get_ctor($base, $ctor, exists ${"${class}::ISA"}{$base} ? ${"${class}::ISA"}{$base} : '@_'); | 81 : _chain_call( *{"${class}::CTOR"}{CODE}, $prev ); |
| 82 | |
| 83 foreach my $base ( @{"${class}::ISA"} ) { | |
| 84 $ctor = _get_ctor( $base, $ctor, | |
| 85 exists ${"${class}::ISA"}{$base} | |
| 86 ? ${"${class}::ISA"}{$base} | |
| 87 : '@_' ); | |
| 65 } | 88 } |
| 66 | 89 |
| 67 if ($isolate) { | 90 if ($isolate) { |
| 68 $ctor = _chain_call(_chain_params($ctor, $t), $prev); | 91 $ctor = _chain_call( _chain_params( $ctor, $t ), $prev ); |
| 69 } | 92 } |
| 70 | 93 |
| 71 return $ctor; | 94 return $ctor; |
| 72 } | 95 } |
| 73 | 96 |
| 74 sub _get_dtor { | 97 sub _get_dtor { |
| 75 my ($class, $prev) = @_; | 98 my ( $class, $prev ) = @_; |
| 76 no strict 'refs'; | 99 no strict 'refs'; |
| 77 | 100 |
| 78 my $dtor = _chain_call(*{"${class}::DTOR"}{CODE}, $prev); | 101 my $dtor = _chain_call( *{"${class}::DTOR"}{CODE}, $prev ); |
| 79 $dtor = _get_dtor($_, $dtor) foreach @{"${class}::ISA"}; | 102 $dtor = _get_dtor( $_, $dtor ) foreach @{"${class}::ISA"}; |
| 80 | 103 |
| 81 return $dtor; | 104 return $dtor; |
| 82 } | 105 } |
| 83 | 106 |
| 84 sub _chain_call { | 107 sub _chain_call { |
| 85 my ($method, $next) = @_; | 108 my ( $method, $next ) = @_; |
| 86 | 109 |
| 87 return $method unless $next; | 110 return $method unless $next; |
| 88 return $next unless $method; | 111 return $next unless $method; |
| 89 | 112 |
| 90 return sub { &$method(@_); goto &$next; } | 113 return sub { &$method(@_); goto &$next; } |
| 91 } | 114 } |
| 92 | 115 |
| 93 sub _chain_params { | 116 sub _chain_params { |
| 94 my ($method, $prepare) = @_; | 117 my ( $method, $prepare ) = @_; |
| 95 | 118 |
| 96 return unless $method; | 119 return unless $method; |
| 97 | 120 |
| 98 if (not defined $prepare) { | 121 if ( not defined $prepare ) { |
| 99 return sub { @_ = (shift); goto &$method }; | 122 return sub { @_ = (shift); goto &$method }; |
| 100 } elsif ($prepare eq '@_') { | 123 } |
| 124 elsif ( $prepare eq '@_' ) { | |
| 101 return $method; | 125 return $method; |
| 102 } elsif (ref $prepare eq 'CODE') { | 126 } |
| 127 elsif ( ref $prepare eq 'CODE' ) { | |
| 103 return sub { | 128 return sub { |
| 104 @_ = (shift, &$prepare(@_)); | 129 @_ = ( shift, &$prepare(@_) ); |
| 105 goto &$method; | 130 goto &$method; |
| 106 } | 131 } |
| 107 } | 132 } |
| 108 } | 133 } |
| 109 | 134 |
| 110 1; | 135 1; |
