File Coverage

blib/lib/Tangence/Class.pm
Criterion Covered Total %
statement 126 128 98.4
branch 6 8 75.0
condition 9 17 52.9
subroutine 22 22 100.0
pod 5 10 50.0
total 168 185 90.8


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2010-2022 -- leonerd@leonerd.org.uk
5              
6 14     14   1236 use v5.26;
  14         48  
7 14     14   744 use Object::Pad 0.66;
  14         10698  
  14         74  
8              
9             package Tangence::Class 0.30;
10 14     14   7853 class Tangence::Class :isa(Tangence::Meta::Class);
  14         37  
  14         478  
11              
12 14     14   2587 use Tangence::Constants;
  14         29  
  14         2467  
13              
14 14     14   6038 use Tangence::Property;
  14         42  
  14         660  
15              
16 14     14   5783 use Tangence::Meta::Method;
  14         35  
  14         556  
17 14     14   5269 use Tangence::Meta::Event;
  14         35  
  14         545  
18 14     14   5140 use Tangence::Meta::Argument;
  14         46  
  14         536  
19              
20 14     14   92 use Carp;
  14         27  
  14         1020  
21              
22 14     14   5043 use Sub::Util 1.40 qw( set_subname );
  14         3963  
  14         19231  
23              
24             our %CLASSES; # cache one per class, keyed by _Tangence_ class name
25              
26 38         72 sub make ( $class, %args )
27 38     38 0 76 {
  38         99  
  38         64  
28 38         88 my $name = $args{name};
29              
30 38   33     529 return $CLASSES{$name} //= $class->new( %args );
31             }
32              
33             sub _new_type ( $sig )
34 60     60   91 {
  60         95  
  60         70  
35 60         183 return Tangence::Type->make_from_sig( $sig );
36             }
37              
38 26         68 sub declare ( $class, $perlname, %args )
  26         50  
39 26     26 0 66 {
  26         70  
  26         41  
40 26         162 ( my $name = $perlname ) =~ s{::}{.}g;
41              
42 26 50       140 if( exists $CLASSES{$name} ) {
43 0         0 croak "Cannot re-declare $name";
44             }
45              
46 26         104 my $self = $class->make( name => $name );
47              
48 26         59 my %methods;
49 26         51 foreach ( keys %{ $args{methods} } ) {
  26         106  
50 12         32 my %params = %{ $args{methods}{$_} };
  12         61  
51             $methods{$_} = Tangence::Meta::Method->new(
52             class => $self,
53             name => $_,
54             arguments => [ map {
55 12         52 Tangence::Meta::Argument->new( name => $_->[0], type => _new_type( $_->[1] ) )
56 12         40 } @{ delete $params{args} } ],
57 12         41 ret => _new_type( delete $params{ret} ),
58             %params,
59             );
60             }
61              
62 26         56 my %events;
63 26         178 foreach ( keys %{ $args{events} } ) {
  26         102  
64 38         68 my %params = %{ $args{events}{$_} };
  38         130  
65             $events{$_} = Tangence::Meta::Event->new(
66             class => $self,
67             name => $_,
68             arguments => [ map {
69 24         73 Tangence::Meta::Argument->new( name => $_->[0], type => _new_type( $_->[1] ) )
70 38         88 } @{ delete $params{args} } ],
  38         214  
71             %params,
72             );
73             }
74              
75 26         69 my %properties;
76 26         55 foreach ( keys %{ $args{props} } ) {
  26         102  
77 12         27 my %params = %{ $args{props}{$_} };
  12         52  
78             $properties{$_} = Tangence::Property->new(
79             class => $self,
80             name => $_,
81             dimension => ( delete $params{dim} ) || DIM_SCALAR,
82 12   50     75 type => _new_type( delete $params{type} ),
83             %params,
84             );
85             }
86              
87 26         60 my @superclasses;
88 26         47 foreach ( @{ $args{superclasses} } ) {
  26         78  
89 0         0 push @superclasses, Tangence::Class->for_perlname( $_ );
90             }
91              
92             $self->define(
93 26         120 methods => \%methods,
94             events => \%events,
95             properties => \%properties,
96             superclasses => \@superclasses,
97             );
98             }
99              
100             method define
101 38     38 1 106 {
102 38         247 $self->SUPER::define( @_ );
103              
104 38         177 my $class = $self->perlname;
105              
106 38         77 my %subs;
107              
108 38         70 foreach my $prop ( values %{ $self->direct_properties } ) {
  38         177  
109 94         307 $prop->build_accessor( \%subs );
110             }
111              
112 14     14   117 no strict 'refs';
  14         29  
  14         17342  
113 38         302 foreach my $name ( keys %subs ) {
114 466 50       664 next if defined &{"${class}::${name}"};
  466         1855  
115 466         1933 *{"${class}::${name}"} = set_subname "${class}::${name}" => $subs{$name};
  466         1807  
116             }
117             }
118              
119 19         33 sub for_name ( $class, $name )
120 19     19 0 45 {
  19         40  
  19         32  
121 19   33     196 return $CLASSES{$name} // croak "Unknown Tangence::Class for '$name'";
122             }
123              
124 335         487 sub for_perlname ( $class, $perlname )
125 335     335 0 502 {
  335         461  
  335         420  
126 335         1125 ( my $name = $perlname ) =~ s{::}{.}g;
127 335   33     1573 return $CLASSES{$name} // croak "Unknown Tangence::Class for '$perlname'";
128             }
129              
130             sub superclasses
131             {
132 455     455 1 682 my $self = shift;
133              
134 455         1158 my @supers = $self->SUPER::superclasses;
135              
136 455 100 100     1682 if( !@supers and $self->perlname ne "Tangence::Object" ) {
137 296         720 @supers = Tangence::Class->for_perlname( "Tangence::Object" );
138             }
139              
140 455         1451 return @supers;
141             }
142              
143 6         12 method method ( $name )
  6         11  
  6         11  
144 6     6 1 18 {
145 6         30 return $self->methods->{$name};
146             }
147              
148 49         78 method event ( $name )
  49         86  
  49         110  
149 49     49 1 139 {
150 49         180 return $self->events->{$name};
151             }
152              
153 194         262 method property ( $name )
  194         286  
  194         232  
154 194     194 1 447 {
155 194         463 return $self->properties->{$name};
156             }
157              
158             field $smashkeys;
159              
160             method smashkeys
161 41     41 0 99 {
162 41   66     153 return $smashkeys //= do {
163 19         46 my %smash;
164 19         45 $smash{$_->name} = 1 for grep { $_->smashed } values %{ $self->properties };
  83         219  
  19         59  
165 19 100       152 $Tangence::Message::SORT_HASH_KEYS ? [ sort keys %smash ] : [ keys %smash ];
166             };
167             }
168              
169             =head1 AUTHOR
170              
171             Paul Evans
172              
173             =cut
174              
175             0x55AA;