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-2021 -- leonerd@leonerd.org.uk
5              
6 14     14   1040 use v5.26;
  14         40  
7 14     14   545 use Object::Pad 0.41;
  14         8125  
  14         64  
8              
9             package Tangence::Class 0.28;
10 14     14   6562 class Tangence::Class isa Tangence::Meta::Class;
  14         31  
  14         695  
11              
12 14     14   2447 use Tangence::Constants;
  14         25  
  14         2213  
13              
14 14     14   5719 use Tangence::Property;
  14         38  
  14         604  
15              
16 14     14   5639 use Tangence::Meta::Method;
  14         29  
  14         482  
17 14     14   4925 use Tangence::Meta::Event;
  14         28  
  14         463  
18 14     14   4948 use Tangence::Meta::Argument;
  14         30  
  14         449  
19              
20 14     14   78 use Carp;
  14         22  
  14         975  
21              
22 14     14   4717 use Sub::Util 1.40 qw( set_subname );
  14         3477  
  14         16232  
23              
24             our %CLASSES; # cache one per class, keyed by _Tangence_ class name
25              
26 38         63 sub make ( $class, %args )
27 38     38 0 71 {
  38         87  
  38         57  
28 38         78 my $name = $args{name};
29              
30 38   33     494 return $CLASSES{$name} //= $class->new( %args );
31             }
32              
33             sub _new_type ( $sig )
34 60     60   84 {
  60         76  
  60         61  
35 60         174 return Tangence::Type->make_from_sig( $sig );
36             }
37              
38 26         58 sub declare ( $class, $perlname, %args )
  26         43  
39 26     26 0 64 {
  26         70  
  26         39  
40 26         143 ( my $name = $perlname ) =~ s{::}{.}g;
41              
42 26 50       121 if( exists $CLASSES{$name} ) {
43 0         0 croak "Cannot re-declare $name";
44             }
45              
46 26         113 my $self = $class->make( name => $name );
47              
48 26         55 my %methods;
49 26         47 foreach ( keys %{ $args{methods} } ) {
  26         100  
50 12         30 my %params = %{ $args{methods}{$_} };
  12         56  
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         37 } @{ delete $params{args} } ],
57 12         36 ret => _new_type( delete $params{ret} ),
58             %params,
59             );
60             }
61              
62 26         88 my %events;
63 26         40 foreach ( keys %{ $args{events} } ) {
  26         85  
64 38         63 my %params = %{ $args{events}{$_} };
  38         123  
65             $events{$_} = Tangence::Meta::Event->new(
66             class => $self,
67             name => $_,
68             arguments => [ map {
69 24         61 Tangence::Meta::Argument->new( name => $_->[0], type => _new_type( $_->[1] ) )
70 38         75 } @{ delete $params{args} } ],
  38         202  
71             %params,
72             );
73             }
74              
75 26         61 my %properties;
76 26         41 foreach ( keys %{ $args{props} } ) {
  26         76  
77 12         25 my %params = %{ $args{props}{$_} };
  12         46  
78             $properties{$_} = Tangence::Property->new(
79             class => $self,
80             name => $_,
81             dimension => ( delete $params{dim} ) || DIM_SCALAR,
82 12   50     70 type => _new_type( delete $params{type} ),
83             %params,
84             );
85             }
86              
87 26         50 my @superclasses;
88 26         40 foreach ( @{ $args{superclasses} } ) {
  26         70  
89 0         0 push @superclasses, Tangence::Class->for_perlname( $_ );
90             }
91              
92             $self->define(
93 26         106 methods => \%methods,
94             events => \%events,
95             properties => \%properties,
96             superclasses => \@superclasses,
97             );
98             }
99              
100             method define
101 38     38 1 107 {
102 38         225 $self->SUPER::define( @_ );
103              
104 38         161 my $class = $self->perlname;
105              
106 38         77 my %subs;
107              
108 38         65 foreach my $prop ( values %{ $self->direct_properties } ) {
  38         143  
109 94         274 $prop->build_accessor( \%subs );
110             }
111              
112 14     14   122 no strict 'refs';
  14         37  
  14         15053  
113 38         223 foreach my $name ( keys %subs ) {
114 466 50       548 next if defined &{"${class}::${name}"};
  466         1730  
115 466         1633 *{"${class}::${name}"} = set_subname "${class}::${name}" => $subs{$name};
  466         1702  
116             }
117             }
118              
119 19         32 sub for_name ( $class, $name )
120 19     19 0 43 {
  19         38  
  19         31  
121 19   33     161 return $CLASSES{$name} // croak "Unknown Tangence::Class for '$name'";
122             }
123              
124 335         470 sub for_perlname ( $class, $perlname )
125 335     335 0 440 {
  335         476  
  335         372  
126 335         1073 ( my $name = $perlname ) =~ s{::}{.}g;
127 335   33     1468 return $CLASSES{$name} // croak "Unknown Tangence::Class for '$perlname'";
128             }
129              
130             sub superclasses
131             {
132 455     455 1 593 my $self = shift;
133              
134 455         1157 my @supers = $self->SUPER::superclasses;
135              
136 455 100 100     1614 if( !@supers and $self->perlname ne "Tangence::Object" ) {
137 296         780 @supers = Tangence::Class->for_perlname( "Tangence::Object" );
138             }
139              
140 455         1275 return @supers;
141             }
142              
143 6         17 method method ( $name )
  6         10  
  6         7  
144 6     6 1 16 {
145 6         30 return $self->methods->{$name};
146             }
147              
148 49         67 method event ( $name )
  49         81  
  49         65  
149 49     49 1 121 {
150 49         206 return $self->events->{$name};
151             }
152              
153 194         236 method property ( $name )
  194         252  
  194         217  
154 194     194 1 411 {
155 194         485 return $self->properties->{$name};
156             }
157              
158             has $smashkeys;
159              
160             method smashkeys
161 41     41 0 86 {
162 41   66     147 return $smashkeys //= do {
163 19         86 my %smash;
164 19         32 $smash{$_->name} = 1 for grep { $_->smashed } values %{ $self->properties };
  83         197  
  19         67  
165 19 100       130 $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;