line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Type::Alias; |
2
|
4
|
|
|
4
|
|
358502
|
use strict; |
|
4
|
|
|
|
|
35
|
|
|
4
|
|
|
|
|
120
|
|
3
|
4
|
|
|
4
|
|
21
|
use warnings; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
168
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
our $VERSION = "0.02"; |
6
|
|
|
|
|
|
|
|
7
|
4
|
|
|
4
|
|
20
|
use feature qw(state); |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
550
|
|
8
|
4
|
|
|
4
|
|
26
|
use Carp qw(croak); |
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
231
|
|
9
|
4
|
|
|
4
|
|
24
|
use Scalar::Util qw(blessed); |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
184
|
|
10
|
4
|
|
|
4
|
|
1968
|
use Types::Standard qw(ArrayRef Dict Tuple); |
|
4
|
|
|
|
|
241905
|
|
|
4
|
|
|
|
|
34
|
|
11
|
4
|
|
|
4
|
|
5969
|
use B::Hooks::EndOfScope qw(on_scope_end); |
|
4
|
|
|
|
|
42972
|
|
|
4
|
|
|
|
|
27
|
|
12
|
4
|
|
|
4
|
|
402
|
use Variable::Magic qw(wizard cast dispell); |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
1177
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub import { |
15
|
10
|
|
|
10
|
|
5933
|
my ($class, %args) = @_; |
16
|
|
|
|
|
|
|
|
17
|
10
|
|
|
|
|
27
|
my $target_package = caller; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# define type alias function |
20
|
10
|
|
100
|
|
|
52
|
my $type_alias_function_name = $args{'-type_alias'} // 'type'; |
21
|
10
|
|
|
|
|
37
|
$class->_import_type_alias_function($target_package, $type_alias_function_name); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# predefine type aliases |
24
|
9
|
|
50
|
|
|
33
|
my $type_aliases = $args{'-declare'} // []; |
25
|
9
|
|
|
|
|
22
|
$class->_import_type_aliases($target_package, $type_aliases); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# push @EXPORT_OK => @type_aliases |
28
|
8
|
100
|
|
|
|
18
|
if ($args{'-export_ok'}) { |
29
|
2
|
|
|
|
|
5
|
for my $export (@{ $args{'-export_ok'} }) { |
|
2
|
|
|
|
|
5
|
|
30
|
2
|
100
|
|
|
|
13
|
unless (grep { $_ eq $export } @$type_aliases) { |
|
3
|
|
|
|
|
16
|
|
31
|
1
|
|
|
|
|
127
|
croak "Type alias '$export' is not declared. should fix -declare or -export_ok."; |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
} |
35
|
7
|
|
66
|
|
|
26
|
my $export_ok = $args{'-export_ok'} // $type_aliases; |
36
|
|
|
|
|
|
|
on_scope_end { |
37
|
7
|
|
|
7
|
|
5478
|
$class->_import_export_ok($target_package, $export_ok); |
38
|
|
|
|
|
|
|
} |
39
|
7
|
|
|
|
|
33
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub _import_type_alias_function { |
42
|
10
|
|
|
10
|
|
21
|
my ($class, $target_package, $type_alias_function_name) = @_; |
43
|
|
|
|
|
|
|
|
44
|
10
|
100
|
|
|
|
128
|
if ($target_package->can($type_alias_function_name)) { |
45
|
1
|
|
|
|
|
123
|
croak "Alreay exists function '${target_package}::${type_alias_function_name}'. Please use another type alias function name."; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
4
|
|
|
4
|
|
28
|
no strict qw(refs); |
|
4
|
|
|
|
|
20
|
|
|
4
|
|
|
|
|
117
|
|
49
|
4
|
|
|
4
|
|
36
|
no warnings qw(once); |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
256
|
|
50
|
9
|
|
|
|
|
41
|
*{"${target_package}::${type_alias_function_name}"} = sub { |
51
|
4
|
|
|
4
|
|
4235
|
my ($type_alias_name, $type_alias_args) = @_; |
52
|
|
|
|
|
|
|
|
53
|
4
|
|
|
4
|
|
22
|
no strict qw(refs); |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
146
|
|
54
|
4
|
|
|
4
|
|
26
|
no warnings qw(redefine); # Already define empty type alias at _import_type_aliases |
|
4
|
|
|
|
|
28
|
|
|
4
|
|
|
|
|
727
|
|
55
|
4
|
|
|
|
|
11
|
*{"${target_package}::${type_alias_name}"} = generate_type_alias($type_alias_args); |
|
4
|
|
|
|
|
23
|
|
56
|
|
|
|
|
|
|
} |
57
|
9
|
|
|
|
|
65
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub _import_type_aliases { |
60
|
9
|
|
|
9
|
|
20
|
my ($class, $target_package, $type_aliases) = @_; |
61
|
|
|
|
|
|
|
|
62
|
9
|
|
|
|
|
20
|
for my $type_alias (@$type_aliases) { |
63
|
12
|
100
|
|
|
|
90
|
if ($target_package->can($type_alias)) { |
64
|
1
|
|
|
|
|
152
|
croak "Cannot predeclare type alias '${target_package}::${type_alias}'."; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
4
|
|
|
4
|
|
27
|
no strict qw(refs); |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
657
|
|
68
|
11
|
|
|
|
|
43
|
*{"${target_package}::${type_alias}"} = sub :prototype(;$) { |
69
|
1
|
|
|
1
|
|
1912
|
croak "You should define type alias '$type_alias' before using it." |
70
|
|
|
|
|
|
|
} |
71
|
11
|
|
|
|
|
70
|
} |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub _import_export_ok { |
75
|
7
|
|
|
7
|
|
40
|
my ($class, $target_package, $export_ok) = @_; |
76
|
|
|
|
|
|
|
|
77
|
7
|
|
|
|
|
16
|
my $EXPORT_OK = "${target_package}::EXPORT_OK"; |
78
|
|
|
|
|
|
|
|
79
|
4
|
|
|
4
|
|
28
|
no strict qw(refs); |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
3038
|
|
80
|
7
|
100
|
|
|
|
22
|
if (defined *{$EXPORT_OK}{ARRAY}) { |
|
7
|
|
|
|
|
33
|
|
81
|
5
|
|
|
|
|
18
|
push @{$EXPORT_OK}, @$export_ok; |
|
5
|
|
|
|
|
17
|
|
82
|
|
|
|
|
|
|
|
83
|
5
|
|
|
|
|
7
|
my $wiz; |
84
|
|
|
|
|
|
|
$wiz = wizard( |
85
|
|
|
|
|
|
|
set => sub { |
86
|
3
|
|
|
3
|
|
11276
|
push @{$_[0]} => @$export_ok; |
|
3
|
|
|
|
|
13
|
|
87
|
3
|
|
|
|
|
4
|
dispell @{$EXPORT_OK}, $wiz; |
|
3
|
|
|
|
|
34
|
|
88
|
|
|
|
|
|
|
}, |
89
|
5
|
|
|
|
|
26
|
); |
90
|
5
|
|
|
|
|
165
|
cast @{$EXPORT_OK}, $wiz; |
|
5
|
|
|
|
|
26
|
|
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub to_type { |
95
|
64
|
|
|
64
|
0
|
89084
|
my $v = shift; |
96
|
64
|
100
|
|
|
|
228
|
if (blessed($v)) { |
|
|
100
|
|
|
|
|
|
97
|
42
|
100
|
66
|
|
|
129
|
if ($v->can('check') && $v->can('get_message')) { |
98
|
40
|
|
|
|
|
885
|
return $v; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
else { |
101
|
2
|
|
|
|
|
295
|
croak 'This object is not supported: '. ref $v; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
elsif (ref $v) { |
105
|
18
|
100
|
|
|
|
68
|
if (ref $v eq 'ARRAY') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
106
|
8
|
|
|
|
|
24
|
return Tuple[ map { to_type($_) } @$v ]; |
|
14
|
|
|
|
|
28
|
|
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
elsif (ref $v eq 'HASH') { |
109
|
|
|
|
|
|
|
return Dict[ |
110
|
6
|
|
|
|
|
32
|
map { $_ => to_type($v->{$_}) } sort { $a cmp $b } keys %$v |
|
11
|
|
|
|
|
31
|
|
|
7
|
|
|
|
|
22
|
|
111
|
|
|
|
|
|
|
]; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
elsif (ref $v eq 'CODE') { |
114
|
|
|
|
|
|
|
return sub { |
115
|
7
|
|
|
7
|
|
4709
|
my @args; |
116
|
7
|
100
|
|
|
|
25
|
if (@_) { |
117
|
6
|
100
|
66
|
|
|
38
|
unless (@_ == 1 && ref $_[0] eq 'ARRAY') { |
118
|
1
|
|
|
|
|
153
|
croak 'This type requires an array reference'; |
119
|
|
|
|
|
|
|
} |
120
|
5
|
|
|
|
|
13
|
@args = map { to_type($_) } @{$_[0]}; |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
14
|
|
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
6
|
|
|
|
|
2098
|
to_type($v->(@args)); |
124
|
|
|
|
|
|
|
} |
125
|
3
|
|
|
|
|
16
|
} |
126
|
|
|
|
|
|
|
else { |
127
|
1
|
|
|
|
|
93
|
croak 'This reference is not supported: ' . ref $v ; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
else { |
131
|
|
|
|
|
|
|
# TODO: Is it better to make it a type that checks whether it matches the given value? |
132
|
4
|
100
|
|
|
|
350
|
croak 'This value is not supported: ' . (defined $v ? $v : 'undef'); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub generate_type_alias { |
137
|
8
|
|
|
8
|
0
|
10051
|
my ($type_alias_args) = @_; |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
return sub :prototype(;$) { |
140
|
8
|
|
|
8
|
|
1581
|
state $type = to_type($type_alias_args); |
141
|
|
|
|
|
|
|
|
142
|
8
|
100
|
|
|
|
13971
|
if (@_) { |
143
|
3
|
100
|
|
|
|
12
|
unless (ref $type eq 'CODE') { |
144
|
1
|
|
|
|
|
181
|
croak 'This type does not accept parameters'; |
145
|
|
|
|
|
|
|
} |
146
|
2
|
|
|
|
|
6
|
return $type->(@_); |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
else { |
149
|
5
|
|
|
|
|
30
|
return $type; |
150
|
|
|
|
|
|
|
} |
151
|
8
|
|
|
|
|
43
|
}; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
1; |
155
|
|
|
|
|
|
|
__END__ |