Mercurial > pub > Impl
comparison lib/IMPL/Object/_Base.pm @ 425:c27434cdd611 ref20150831
sync
author | cin |
---|---|
date | Tue, 03 Apr 2018 19:30:01 +0300 |
parents | 87af445663d7 |
children |
comparison
equal
deleted
inserted
replaced
424:87af445663d7 | 425:c27434cdd611 |
---|---|
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; |