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   994 use v5.26;
  14         38  
7 14     14   564 use Object::Pad 0.57;
  14         8462  
  14         56  
8              
9             package Tangence::Class 0.29;
10 14     14   6129 class Tangence::Class :isa(Tangence::Meta::Class);
  14         34  
  14         431  
11              
12 14     14   2291 use Tangence::Constants;
  14         24  
  14         2052  
13              
14 14     14   5221 use Tangence::Property;
  14         34  
  14         560  
15              
16 14     14   4928 use Tangence::Meta::Method;
  14         30  
  14         444  
17 14     14   4816 use Tangence::Meta::Event;
  14         32  
  14         496  
18 14     14   5372 use Tangence::Meta::Argument;
  14         32  
  14         445  
19              
20 14     14   81 use Carp;
  14         35  
  14         966  
21              
22 14     14   4180 use Sub::Util 1.40 qw( set_subname );
  14         3248  
  14         17447  
23              
24             our %CLASSES; # cache one per class, keyed by _Tangence_ class name
25              
26 38         58 sub make ( $class, %args )
27 38     38 0 66 {
  38         129  
  38         52  
28 38         70 my $name = $args{name};
29              
30 38   33     427 return $CLASSES{$name} //= $class->new( %args );
31             }
32              
33             sub _new_type ( $sig )
34 60     60   76 {
  60         75  
  60         64  
35 60         155 return Tangence::Type->make_from_sig( $sig );
36             }
37              
38 26         55 sub declare ( $class, $perlname, %args )
  26         37  
39 26     26 0 54 {
  26         59  
  26         33  
40 26         130 ( my $name = $perlname ) =~ s{::}{.}g;
41              
42 26 50       172 if( exists $CLASSES{$name} ) {
43 0         0 croak "Cannot re-declare $name";
44             }
45              
46 26         76 my $self = $class->make( name => $name );
47              
48 26         49 my %methods;
49 26         48 foreach ( keys %{ $args{methods} } ) {
  26         96  
50 12         25 my %params = %{ $args{methods}{$_} };
  12         48  
51             $methods{$_} = Tangence::Meta::Method->new(
52             class => $self,
53             name => $_,
54             arguments => [ map {
55 12         38 Tangence::Meta::Argument->new( name => $_->[0], type => _new_type( $_->[1] ) )
56 12         33 } @{ delete $params{args} } ],
57 12         32 ret => _new_type( delete $params{ret} ),
58             %params,
59             );
60             }
61              
62 26         46 my %events;
63 26         38 foreach ( keys %{ $args{events} } ) {
  26         77  
64 38         54 my %params = %{ $args{events}{$_} };
  38         112  
65             $events{$_} = Tangence::Meta::Event->new(
66             class => $self,
67             name => $_,
68             arguments => [ map {
69 24         47 Tangence::Meta::Argument->new( name => $_->[0], type => _new_type( $_->[1] ) )
70 38         70 } @{ delete $params{args} } ],
  38         167  
71             %params,
72             );
73             }
74              
75 26         52 my %properties;
76 26         40 foreach ( keys %{ $args{props} } ) {
  26         72  
77 12         25 my %params = %{ $args{props}{$_} };
  12         39  
78             $properties{$_} = Tangence::Property->new(
79             class => $self,
80             name => $_,
81             dimension => ( delete $params{dim} ) || DIM_SCALAR,
82 12   50     57 type => _new_type( delete $params{type} ),
83             %params,
84             );
85             }
86              
87 26         45 my @superclasses;
88 26         47 foreach ( @{ $args{superclasses} } ) {
  26         64  
89 0         0 push @superclasses, Tangence::Class->for_perlname( $_ );
90             }
91              
92             $self->define(
93 26         90 methods => \%methods,
94             events => \%events,
95             properties => \%properties,
96             superclasses => \@superclasses,
97             );
98             }
99              
100             method define
101 38     38 1 99 {
102 38         191 $self->SUPER::define( @_ );
103              
104 38         152 my $class = $self->perlname;
105              
106 38         65 my %subs;
107              
108 38         57 foreach my $prop ( values %{ $self->direct_properties } ) {
  38         127  
109 94         246 $prop->build_accessor( \%subs );
110             }
111              
112 14     14   111 no strict 'refs';
  14         27  
  14         14767  
113 38         209 foreach my $name ( keys %subs ) {
114 466 50       523 next if defined &{"${class}::${name}"};
  466         1543  
115 466         1600 *{"${class}::${name}"} = set_subname "${class}::${name}" => $subs{$name};
  466         1476  
116             }
117             }
118              
119 19         36 sub for_name ( $class, $name )
120 19     19 0 48 {
  19         39  
  19         38  
121 19   33     153 return $CLASSES{$name} // croak "Unknown Tangence::Class for '$name'";
122             }
123              
124 335         403 sub for_perlname ( $class, $perlname )
125 335     335 0 413 {
  335         385  
  335         368  
126 335         944 ( my $name = $perlname ) =~ s{::}{.}g;
127 335   33     1348 return $CLASSES{$name} // croak "Unknown Tangence::Class for '$perlname'";
128             }
129              
130             sub superclasses
131             {
132 455     455 1 580 my $self = shift;
133              
134 455         1001 my @supers = $self->SUPER::superclasses;
135              
136 455 100 100     1496 if( !@supers and $self->perlname ne "Tangence::Object" ) {
137 296         626 @supers = Tangence::Class->for_perlname( "Tangence::Object" );
138             }
139              
140 455         1238 return @supers;
141             }
142              
143 6         12 method method ( $name )
  6         13  
  6         17  
144 6     6 1 16 {
145 6         42 return $self->methods->{$name};
146             }
147              
148 49         67 method event ( $name )
  49         72  
  49         58  
149 49     49 1 114 {
150 49         171 return $self->events->{$name};
151             }
152              
153 194         220 method property ( $name )
  194         236  
  194         205  
154 194     194 1 388 {
155 194         397 return $self->properties->{$name};
156             }
157              
158             has $smashkeys;
159              
160             method smashkeys
161 41     41 0 83 {
162 41   66     135 return $smashkeys //= do {
163 19         32 my %smash;
164 19         28 $smash{$_->name} = 1 for grep { $_->smashed } values %{ $self->properties };
  83         194  
  19         51  
165 19 100       135 $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;