| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Sub::Quote; |
|
2
|
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
63
|
sub _clean_eval { eval $_[0] } |
|
|
5
|
|
|
40
|
|
15
|
|
|
|
5
|
|
|
1
|
|
177
|
|
|
|
40
|
|
|
1
|
|
5015
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
11
|
|
|
11
|
|
578745
|
use strict; |
|
|
10
|
|
|
|
|
75
|
|
|
|
10
|
|
|
|
|
400
|
|
|
6
|
11
|
|
|
11
|
|
53
|
use warnings; |
|
|
11
|
|
|
|
|
20
|
|
|
|
11
|
|
|
|
|
320
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
11
|
|
|
11
|
|
14498
|
use Sub::Defer qw(defer_sub); |
|
|
10
|
|
|
|
|
22
|
|
|
|
10
|
|
|
|
|
449
|
|
|
9
|
11
|
|
|
11
|
|
61
|
use Scalar::Util qw(weaken); |
|
|
11
|
|
|
|
|
18
|
|
|
|
11
|
|
|
|
|
396
|
|
|
10
|
11
|
|
|
11
|
|
52
|
use Exporter qw(import); |
|
|
11
|
|
|
|
|
20
|
|
|
|
11
|
|
|
|
|
378
|
|
|
11
|
11
|
|
|
11
|
|
74
|
use Carp qw(croak); |
|
|
12
|
|
|
|
|
28
|
|
|
|
12
|
|
|
|
|
444
|
|
|
12
|
11
|
|
|
11
|
|
216
|
BEGIN { our @CARP_NOT = qw(Sub::Defer) } |
|
13
|
11
|
|
|
11
|
|
83
|
use B (); |
|
|
12
|
|
|
|
|
61
|
|
|
|
12
|
|
|
|
|
2456
|
|
|
14
|
|
|
|
|
|
|
BEGIN { |
|
15
|
11
|
100
|
|
11
|
|
325
|
*_HAVE_IS_UTF8 = defined &utf8::is_utf8 ? sub(){1} : sub(){0}; |
|
16
|
11
|
100
|
|
|
|
78
|
*_HAVE_PERLSTRING = defined &B::perlstring ? sub(){1} : sub(){0}; |
|
17
|
11
|
50
|
66
|
|
|
135
|
*_BAD_BACKSLASH_ESCAPE = _HAVE_PERLSTRING() && "$]" == 5.010_000 ? sub(){1} : sub(){0}; |
|
18
|
11
|
100
|
66
|
|
|
514
|
*_HAVE_HEX_FLOAT = !$ENV{SUB_QUOTE_NO_HEX_FLOAT} && "$]" >= 5.022 ? sub(){1} : sub(){0}; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# This may not be perfect, as we can't tell the format purely from the size |
|
21
|
|
|
|
|
|
|
# but it should cover the common cases, and other formats are more likely to |
|
22
|
|
|
|
|
|
|
# be less precise. |
|
23
|
11
|
|
|
|
|
120
|
my $nvsize = 8 * length pack 'F', 0; |
|
24
|
10
|
0
|
|
|
|
38
|
my $nvmantbits |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
= $nvsize == 16 ? 11 |
|
26
|
|
|
|
|
|
|
: $nvsize == 32 ? 24 |
|
27
|
|
|
|
|
|
|
: $nvsize == 64 ? 53 |
|
28
|
|
|
|
|
|
|
: $nvsize == 80 ? 64 |
|
29
|
|
|
|
|
|
|
: $nvsize == 128 ? 113 |
|
30
|
|
|
|
|
|
|
: $nvsize == 256 ? 237 |
|
31
|
|
|
|
|
|
|
: 237 # unknown float format |
|
32
|
|
|
|
|
|
|
; |
|
33
|
10
|
|
|
|
|
74
|
my $precision = int( log(2)/log(10)*$nvmantbits ); |
|
34
|
|
|
|
|
|
|
|
|
35
|
9
|
|
|
|
|
126
|
*_NVSIZE = sub(){$nvsize}; |
|
|
1
|
|
|
|
|
6
|
|
|
36
|
9
|
|
|
|
|
36
|
*_NVMANTBITS = sub(){$nvmantbits}; |
|
|
1
|
|
|
|
|
76
|
|
|
37
|
9
|
|
|
|
|
1744
|
*_FLOAT_PRECISION = sub(){$precision}; |
|
|
1
|
|
|
|
|
3
|
|
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
our $VERSION = '2.006006'; |
|
41
|
|
|
|
|
|
|
$VERSION =~ tr/_//d; |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
our @EXPORT = qw(quote_sub unquote_sub quoted_from_sub qsub); |
|
44
|
|
|
|
|
|
|
our @EXPORT_OK = qw(quotify capture_unroll inlinify sanitize_identifier); |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
our %QUOTED; |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
my %escape; |
|
49
|
|
|
|
|
|
|
if (_BAD_BACKSLASH_ESCAPE) { |
|
50
|
|
|
|
|
|
|
%escape = ( |
|
51
|
|
|
|
|
|
|
(map +(chr($_) => sprintf '\x%02x', $_), 0 .. 0x31, 0x7f), |
|
52
|
|
|
|
|
|
|
"\t" => "\\t", |
|
53
|
|
|
|
|
|
|
"\n" => "\\n", |
|
54
|
|
|
|
|
|
|
"\r" => "\\r", |
|
55
|
|
|
|
|
|
|
"\f" => "\\f", |
|
56
|
|
|
|
|
|
|
"\b" => "\\b", |
|
57
|
|
|
|
|
|
|
"\a" => "\\a", |
|
58
|
|
|
|
|
|
|
"\e" => "\\e", |
|
59
|
|
|
|
|
|
|
(map +($_ => "\\$_"), qw(" \ $ @)), |
|
60
|
|
|
|
|
|
|
); |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub quotify { |
|
64
|
2366
|
|
|
2366
|
1
|
4414705
|
my $value = $_[0]; |
|
65
|
9
|
|
|
11
|
|
89
|
no warnings 'numeric'; |
|
|
9
|
|
|
|
|
19
|
|
|
|
9
|
|
|
|
|
19054
|
|
|
66
|
|
|
|
|
|
|
! defined $value ? 'undef()' |
|
67
|
|
|
|
|
|
|
# numeric detection |
|
68
|
|
|
|
|
|
|
: (!(_HAVE_IS_UTF8 && utf8::is_utf8($value)) |
|
69
|
|
|
|
|
|
|
&& length( (my $dummy = '') & $value ) |
|
70
|
|
|
|
|
|
|
&& 0 + $value eq $value |
|
71
|
|
|
|
|
|
|
) ? ( |
|
72
|
|
|
|
|
|
|
$value != $value ? ( |
|
73
|
|
|
|
|
|
|
$value eq (9**9**9*0) |
|
74
|
|
|
|
|
|
|
? '(9**9**9*0)' # nan |
|
75
|
|
|
|
|
|
|
: '(-(9**9**9*0))' # -nan |
|
76
|
|
|
|
|
|
|
) |
|
77
|
|
|
|
|
|
|
: $value == 9**9**9 ? '(9**9**9)' # inf |
|
78
|
|
|
|
|
|
|
: $value == -9**9**9 ? '(-9**9**9)' # -inf |
|
79
|
|
|
|
|
|
|
: $value == 0 ? ( |
|
80
|
|
|
|
|
|
|
sprintf('%g', $value) eq '-0' ? '-0.0' : '0', |
|
81
|
|
|
|
|
|
|
) |
|
82
|
|
|
|
|
|
|
: $value !~ /[e.]/i ? ( |
|
83
|
|
|
|
|
|
|
$value > 0 ? (sprintf '%u', $value) |
|
84
|
|
|
|
|
|
|
: (sprintf '%d', $value) |
|
85
|
|
|
|
|
|
|
) |
|
86
|
|
|
|
|
|
|
: do { |
|
87
|
164
|
|
|
|
|
366
|
my $float = $value; |
|
88
|
164
|
|
|
|
|
565
|
my $max_factor = int( log( abs($value) ) / log(2) ) - _NVMANTBITS; |
|
89
|
164
|
100
|
|
|
|
310
|
my $ex_sign = $max_factor > 0 ? 1 : -1; |
|
90
|
164
|
|
|
|
|
406
|
FACTOR: for my $ex (0 .. abs($max_factor)) { |
|
91
|
172
|
|
|
|
|
350
|
my $num = $value / 2**($ex_sign * $ex); |
|
92
|
172
|
|
|
|
|
245
|
for my $precision (_FLOAT_PRECISION .. _FLOAT_PRECISION+2) { |
|
93
|
317
|
|
|
|
|
1239
|
my $formatted = sprintf '%.'.$precision.'g', $num; |
|
94
|
317
|
100
|
|
|
|
593
|
$float = $formatted |
|
95
|
|
|
|
|
|
|
if $ex == 0; |
|
96
|
317
|
100
|
|
|
|
809
|
if ($formatted == $num) { |
|
97
|
158
|
100
|
|
|
|
360
|
if ($ex) { |
|
98
|
5
|
50
|
|
|
|
26
|
$float |
|
|
|
50
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
= $formatted |
|
100
|
|
|
|
|
|
|
. ($ex_sign == 1 ? '*' : '/') |
|
101
|
|
|
|
|
|
|
. ( |
|
102
|
|
|
|
|
|
|
$ex > _NVMANTBITS |
|
103
|
|
|
|
|
|
|
? "2**$ex" |
|
104
|
|
|
|
|
|
|
: sprintf('%u', 2**$ex) |
|
105
|
|
|
|
|
|
|
); |
|
106
|
|
|
|
|
|
|
} |
|
107
|
158
|
|
|
|
|
356
|
last FACTOR; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
} |
|
110
|
19
|
|
|
|
|
167
|
if (_HAVE_HEX_FLOAT) { |
|
111
|
65
|
|
|
|
|
189
|
$float = sprintf '%a', $value; |
|
112
|
11
|
|
|
|
|
32
|
last FACTOR; |
|
113
|
|
|
|
|
|
|
} |
|
114
|
|
|
|
|
|
|
} |
|
115
|
112
|
|
|
|
|
366
|
"$float"; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
) |
|
118
|
|
|
|
|
|
|
: !length($value) && length( (my $dummy2 = '') & $value ) ? '(!1)' # false |
|
119
|
2366
|
100
|
100
|
|
|
25656
|
: _BAD_BACKSLASH_ESCAPE && _HAVE_IS_UTF8 && utf8::is_utf8($value) ? do { |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
$value =~ s/(["\$\@\\[:cntrl:]]|[^\x00-\x7f])/ |
|
121
|
|
|
|
|
|
|
$escape{$1} || sprintf('\x{%x}', ord($1)) |
|
122
|
|
|
|
|
|
|
/ge; |
|
123
|
|
|
|
|
|
|
qq["$value"]; |
|
124
|
|
|
|
|
|
|
} |
|
125
|
|
|
|
|
|
|
: _HAVE_PERLSTRING ? B::perlstring($value) |
|
126
|
|
|
|
|
|
|
: qq["\Q$value\E"]; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub sanitize_identifier { |
|
130
|
3
|
|
|
3
|
1
|
477
|
my $name = shift; |
|
131
|
3
|
|
|
|
|
12
|
$name =~ s/([_\W])/sprintf('_%x', ord($1))/ge; |
|
|
6
|
|
|
|
|
44
|
|
|
132
|
2
|
|
|
|
|
35
|
$name; |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub capture_unroll { |
|
136
|
43
|
|
|
44
|
1
|
1635
|
my ($from, $captures, $indent) = @_; |
|
137
|
|
|
|
|
|
|
join( |
|
138
|
|
|
|
|
|
|
'', |
|
139
|
|
|
|
|
|
|
map { |
|
140
|
43
|
100
|
|
|
|
104
|
/^([\@\%\$])/ |
|
|
89
|
|
|
|
|
601
|
|
|
141
|
|
|
|
|
|
|
or croak "capture key should start with \@, \% or \$: $_"; |
|
142
|
87
|
|
|
|
|
293
|
(' ' x $indent).qq{my ${_} = ${1}{${from}->{${\quotify $_}}};\n}; |
|
|
87
|
|
|
|
|
136
|
|
|
143
|
|
|
|
|
|
|
} keys %$captures |
|
144
|
|
|
|
|
|
|
); |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub inlinify { |
|
148
|
9
|
|
|
10
|
1
|
8805
|
my ($code, $args, $extra, $local) = @_; |
|
149
|
9
|
100
|
|
|
|
74
|
$args = '()' |
|
150
|
|
|
|
|
|
|
if !defined $args; |
|
151
|
9
|
|
100
|
|
|
29
|
my $do = 'do { '.($extra||''); |
|
152
|
9
|
100
|
|
|
|
36
|
if ($code =~ s/^(\s*package\s+([a-zA-Z0-9:]+);)//) { |
|
153
|
2
|
|
|
|
|
77
|
$do .= $1; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
9
|
100
|
100
|
|
|
47
|
if ($code =~ s{ |
|
|
|
100
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
\A((?:\#\ BEGIN\ quote_sub\ PRELUDE\n.*?\#\ END\ quote_sub\ PRELUDE\n)?\s*) |
|
157
|
|
|
|
|
|
|
(^\s*) my \s* \(([^)]+)\) \s* = \s* \@_; |
|
158
|
|
|
|
|
|
|
}{}xms) { |
|
159
|
4
|
|
|
|
|
13
|
my ($pre, $indent, $code_args) = ($1, $2, $3); |
|
160
|
4
|
|
|
|
|
48
|
$do .= $pre; |
|
161
|
4
|
100
|
|
|
|
14
|
if ($code_args ne $args) { |
|
162
|
2
|
|
|
|
|
6
|
$do .= $indent . 'my ('.$code_args.') = ('.$args.'); '; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
elsif ($local || $args ne '@_') { |
|
166
|
4
|
100
|
|
|
|
93
|
$do .= ($local ? 'local ' : '').'@_ = ('.$args.'); '; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
9
|
|
|
|
|
40
|
$do.$code.' }'; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub quote_sub { |
|
172
|
|
|
|
|
|
|
# HOLY DWIMMERY, BATMAN! |
|
173
|
|
|
|
|
|
|
# $name => $code => \%captures => \%options |
|
174
|
|
|
|
|
|
|
# $name => $code => \%captures |
|
175
|
|
|
|
|
|
|
# $name => $code |
|
176
|
|
|
|
|
|
|
# $code => \%captures => \%options |
|
177
|
|
|
|
|
|
|
# $code |
|
178
|
60
|
100
|
100
|
61
|
1
|
22940
|
my $options = |
|
179
|
|
|
|
|
|
|
(ref($_[-1]) eq 'HASH' and ref($_[-2]) eq 'HASH') |
|
180
|
|
|
|
|
|
|
? pop |
|
181
|
|
|
|
|
|
|
: {}; |
|
182
|
60
|
100
|
|
|
|
187
|
my $captures = ref($_[-1]) eq 'HASH' ? pop : undef; |
|
183
|
60
|
100
|
100
|
|
|
181
|
undef($captures) if $captures && !keys %$captures; |
|
184
|
60
|
|
|
|
|
80
|
my $code = pop; |
|
185
|
60
|
|
|
|
|
115
|
my $name = $_[0]; |
|
186
|
60
|
100
|
|
|
|
103
|
if ($name) { |
|
187
|
22
|
|
|
|
|
26
|
my $subname = $name; |
|
188
|
22
|
100
|
|
|
|
177
|
my $package = $subname =~ s/(.*)::// ? $1 : caller; |
|
189
|
22
|
|
|
|
|
60
|
$name = join '::', $package, $subname; |
|
190
|
22
|
100
|
|
|
|
337
|
croak qq{package name "$package" too long!} |
|
191
|
|
|
|
|
|
|
if length $package > 252; |
|
192
|
20
|
100
|
|
|
|
294
|
croak qq{package name "$package" is not valid!} |
|
193
|
|
|
|
|
|
|
unless $package =~ /^[^\d\W]\w*(?:::\w+)*$/; |
|
194
|
18
|
100
|
|
|
|
116
|
croak qq{sub name "$subname" too long!} |
|
195
|
|
|
|
|
|
|
if length $subname > 252; |
|
196
|
17
|
100
|
|
|
|
196
|
croak qq{sub name "$subname" is not valid!} |
|
197
|
|
|
|
|
|
|
unless $subname =~ /^[^\d\W]\w*$/; |
|
198
|
|
|
|
|
|
|
} |
|
199
|
53
|
|
|
|
|
579
|
my @caller = caller(0); |
|
200
|
53
|
|
|
|
|
909
|
my ($attributes, $file, $line) = @{$options}{qw(attributes file line)}; |
|
|
53
|
|
|
|
|
107
|
|
|
201
|
52
|
100
|
|
|
|
96
|
if ($attributes) { |
|
202
|
|
|
|
|
|
|
/\A\w+(?:\(.*\))?\z/s || croak "invalid attribute $_" |
|
203
|
3
|
|
66
|
|
|
141
|
for @$attributes; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
my $quoted_info = { |
|
206
|
|
|
|
|
|
|
name => $name, |
|
207
|
|
|
|
|
|
|
code => $code, |
|
208
|
|
|
|
|
|
|
captures => $captures, |
|
209
|
|
|
|
|
|
|
package => (exists $options->{package} ? $options->{package} : $caller[0]), |
|
210
|
|
|
|
|
|
|
hints => (exists $options->{hints} ? $options->{hints} : $caller[8]), |
|
211
|
|
|
|
|
|
|
warning_bits => (exists $options->{warning_bits} ? $options->{warning_bits} : $caller[9]), |
|
212
|
51
|
100
|
|
|
|
347
|
hintshash => (exists $options->{hintshash} ? $options->{hintshash} : $caller[10]), |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
($attributes ? (attributes => $attributes) : ()), |
|
214
|
|
|
|
|
|
|
($file ? (file => $file) : ()), |
|
215
|
|
|
|
|
|
|
($line ? (line => $line) : ()), |
|
216
|
|
|
|
|
|
|
}; |
|
217
|
51
|
|
|
|
|
58
|
my $unquoted; |
|
218
|
51
|
|
|
|
|
192
|
weaken($quoted_info->{unquoted} = \$unquoted); |
|
219
|
51
|
100
|
|
|
|
89
|
if ($options->{no_defer}) { |
|
220
|
4
|
|
|
|
|
5
|
my $fake = \my $var; |
|
221
|
4
|
|
|
|
|
10
|
local $QUOTED{$fake} = $quoted_info; |
|
222
|
4
|
|
|
|
|
8
|
my $sub = unquote_sub($fake); |
|
223
|
4
|
100
|
100
|
|
|
18
|
Sub::Defer::_install_coderef($name, $sub) if $name && !$options->{no_install}; |
|
224
|
4
|
|
|
|
|
17
|
return $sub; |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
else { |
|
227
|
|
|
|
|
|
|
my $deferred = defer_sub( |
|
228
|
|
|
|
|
|
|
($options->{no_install} ? undef : $name), |
|
229
|
|
|
|
|
|
|
sub { |
|
230
|
30
|
|
|
32
|
|
33
|
$unquoted if 0; |
|
231
|
30
|
|
|
|
|
52
|
unquote_sub($quoted_info->{deferred}); |
|
232
|
|
|
|
|
|
|
}, |
|
233
|
|
|
|
|
|
|
{ |
|
234
|
|
|
|
|
|
|
($attributes ? ( attributes => $attributes ) : ()), |
|
235
|
47
|
100
|
|
|
|
268
|
($name ? () : ( package => $quoted_info->{package} )), |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
}, |
|
237
|
|
|
|
|
|
|
); |
|
238
|
47
|
|
|
|
|
129
|
weaken($quoted_info->{deferred} = $deferred); |
|
239
|
47
|
|
|
|
|
123
|
weaken($QUOTED{$deferred} = $quoted_info); |
|
240
|
47
|
|
|
|
|
181
|
return $deferred; |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub _context { |
|
245
|
47
|
|
|
49
|
|
78
|
my $info = shift; |
|
246
|
47
|
|
66
|
|
|
108
|
$info->{context} ||= do { |
|
247
|
|
|
|
|
|
|
my ($package, $hints, $warning_bits, $hintshash, $file, $line) |
|
248
|
41
|
|
|
|
|
51
|
= @{$info}{qw(package hints warning_bits hintshash file line)}; |
|
|
41
|
|
|
|
|
146
|
|
|
249
|
|
|
|
|
|
|
|
|
250
|
41
|
100
|
50
|
|
|
74
|
$line ||= 1 |
|
251
|
|
|
|
|
|
|
if $file; |
|
252
|
|
|
|
|
|
|
|
|
253
|
41
|
|
|
|
|
59
|
my $line_mark = ''; |
|
254
|
41
|
100
|
|
|
|
68
|
if ($line) { |
|
255
|
2
|
|
|
|
|
5
|
$line_mark = "#line ".($line-1); |
|
256
|
2
|
100
|
|
|
|
5
|
if ($file) { |
|
257
|
1
|
|
|
|
|
2
|
$line_mark .= qq{ "$file"}; |
|
258
|
|
|
|
|
|
|
} |
|
259
|
2
|
|
|
|
|
2
|
$line_mark .= "\n"; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
$info->{context} |
|
263
|
|
|
|
|
|
|
="# BEGIN quote_sub PRELUDE\n" |
|
264
|
|
|
|
|
|
|
."package $package;\n" |
|
265
|
|
|
|
|
|
|
."BEGIN {\n" |
|
266
|
|
|
|
|
|
|
." \$^H = ".quotify($hints).";\n" |
|
267
|
|
|
|
|
|
|
." \${^WARNING_BITS} = ".quotify($warning_bits).";\n" |
|
268
|
|
|
|
|
|
|
." \%^H = (\n" |
|
269
|
|
|
|
|
|
|
. join('', map |
|
270
|
|
|
|
|
|
|
" ".quotify($_)." => ".quotify($hintshash->{$_}).",\n", |
|
271
|
41
|
|
33
|
|
|
113
|
grep !(ref $hintshash->{$_} && $hintshash->{$_} =~ /\A(?:\w+(?:::\w+)*=)?[A-Z]+\(0x[[0-9a-fA-F]+\)\z/), |
|
272
|
|
|
|
|
|
|
keys %$hintshash) |
|
273
|
|
|
|
|
|
|
." );\n" |
|
274
|
|
|
|
|
|
|
."}\n" |
|
275
|
|
|
|
|
|
|
.$line_mark |
|
276
|
|
|
|
|
|
|
."# END quote_sub PRELUDE\n"; |
|
277
|
|
|
|
|
|
|
}; |
|
278
|
|
|
|
|
|
|
} |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub quoted_from_sub { |
|
281
|
10
|
|
|
15
|
1
|
379
|
my ($sub) = @_; |
|
282
|
10
|
100
|
50
|
|
|
40
|
my $quoted_info = $QUOTED{$sub||''} or return undef; |
|
283
|
|
|
|
|
|
|
my ($name, $code, $captures, $unquoted, $deferred) |
|
284
|
8
|
|
|
|
|
15
|
= @{$quoted_info}{qw(name code captures unquoted deferred)}; |
|
|
8
|
|
|
|
|
20
|
|
|
285
|
8
|
|
|
|
|
17
|
$code = _context($quoted_info) . $code; |
|
286
|
8
|
|
66
|
|
|
51
|
$unquoted &&= $$unquoted; |
|
287
|
8
|
100
|
100
|
|
|
44
|
if (($deferred && $deferred eq $sub) |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
288
|
|
|
|
|
|
|
|| ($unquoted && $unquoted eq $sub)) { |
|
289
|
7
|
|
|
|
|
35
|
return [ $name, $code, $captures, $unquoted, $deferred ]; |
|
290
|
|
|
|
|
|
|
} |
|
291
|
1
|
|
|
|
|
2
|
return undef; |
|
292
|
|
|
|
|
|
|
} |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub unquote_sub { |
|
295
|
43
|
|
|
45
|
1
|
568
|
my ($sub) = @_; |
|
296
|
43
|
100
|
|
|
|
104
|
my $quoted_info = $QUOTED{$sub} or return undef; |
|
297
|
42
|
|
|
|
|
59
|
my $unquoted = $quoted_info->{unquoted}; |
|
298
|
42
|
100
|
66
|
|
|
118
|
unless ($unquoted && $$unquoted) { |
|
299
|
|
|
|
|
|
|
my ($name, $code, $captures, $package, $attributes) |
|
300
|
40
|
|
|
|
|
54
|
= @{$quoted_info}{qw(name code captures package attributes)}; |
|
|
40
|
|
|
|
|
95
|
|
|
301
|
|
|
|
|
|
|
|
|
302
|
40
|
100
|
|
|
|
115
|
($package, $name) = $name =~ /(.*)::(.*)/ |
|
303
|
|
|
|
|
|
|
if $name; |
|
304
|
|
|
|
|
|
|
|
|
305
|
40
|
100
|
|
|
|
79
|
my %captures = $captures ? %$captures : (); |
|
306
|
40
|
|
|
|
|
62
|
$captures{'$_UNQUOTED'} = \$unquoted; |
|
307
|
40
|
|
|
|
|
55
|
$captures{'$_QUOTED'} = \$quoted_info; |
|
308
|
|
|
|
|
|
|
|
|
309
|
40
|
100
|
|
|
|
76
|
my $make_sub |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
= "{\n" |
|
311
|
|
|
|
|
|
|
. capture_unroll("\$_[1]", \%captures, 2) |
|
312
|
|
|
|
|
|
|
. " package ${package};\n" |
|
313
|
|
|
|
|
|
|
. ( |
|
314
|
|
|
|
|
|
|
$name |
|
315
|
|
|
|
|
|
|
# disable the 'variable $x will not stay shared' warning since |
|
316
|
|
|
|
|
|
|
# we're not letting it escape from this scope anyway so there's |
|
317
|
|
|
|
|
|
|
# nothing trying to share it |
|
318
|
|
|
|
|
|
|
? " no warnings 'closure';\n sub ${name} " |
|
319
|
|
|
|
|
|
|
: " \$\$_UNQUOTED = sub " |
|
320
|
|
|
|
|
|
|
) |
|
321
|
|
|
|
|
|
|
. ($attributes ? join('', map ":$_ ", @$attributes) : '') . "{\n" |
|
322
|
|
|
|
|
|
|
. " (\$_QUOTED,\$_UNQUOTED) if 0;\n" |
|
323
|
|
|
|
|
|
|
. _context($quoted_info) |
|
324
|
|
|
|
|
|
|
. $code |
|
325
|
|
|
|
|
|
|
. " }".($name ? "\n \$\$_UNQUOTED = \\&${name}" : '') . ";\n" |
|
326
|
|
|
|
|
|
|
. "}\n" |
|
327
|
|
|
|
|
|
|
. "1;\n"; |
|
328
|
39
|
100
|
|
|
|
119
|
if (my $debug = $ENV{SUB_QUOTE_DEBUG}) { |
|
329
|
12
|
100
|
|
|
|
62
|
if ($debug =~ m{^([^\W\d]\w*(?:::\w+)*(?:::)?)$}) { |
|
|
|
100
|
|
|
|
|
|
|
330
|
9
|
|
|
|
|
18
|
my $filter = $1; |
|
331
|
9
|
100
|
50
|
|
|
36
|
my $match |
|
|
|
100
|
100
|
|
|
|
|
|
332
|
|
|
|
|
|
|
= $filter =~ /::$/ ? $package.'::' |
|
333
|
|
|
|
|
|
|
: $filter =~ /::/ ? $package.'::'.($name||'__ANON__') |
|
334
|
|
|
|
|
|
|
: ($name||'__ANON__'); |
|
335
|
9
|
100
|
|
|
|
42
|
warn $make_sub |
|
336
|
|
|
|
|
|
|
if $match eq $filter; |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
elsif ($debug =~ m{\A/(.*)/\z}s) { |
|
339
|
2
|
|
|
|
|
5
|
my $filter = $1; |
|
340
|
2
|
100
|
|
|
|
20
|
warn $make_sub |
|
341
|
|
|
|
|
|
|
if $code =~ $filter; |
|
342
|
|
|
|
|
|
|
} |
|
343
|
|
|
|
|
|
|
else { |
|
344
|
1
|
|
|
|
|
8
|
warn $make_sub; |
|
345
|
|
|
|
|
|
|
} |
|
346
|
|
|
|
|
|
|
} |
|
347
|
|
|
|
|
|
|
{ |
|
348
|
9
|
|
|
11
|
|
126
|
no strict 'refs'; |
|
|
9
|
|
|
|
|
13
|
|
|
|
9
|
|
|
|
|
2416
|
|
|
|
39
|
|
|
|
|
74
|
|
|
349
|
39
|
100
|
|
|
|
110
|
local *{"${package}::${name}"} if $name; |
|
|
13
|
|
|
|
|
50
|
|
|
350
|
39
|
|
|
|
|
50
|
my ($success, $e); |
|
351
|
|
|
|
|
|
|
{ |
|
352
|
39
|
|
|
|
|
40
|
local $@; |
|
|
39
|
|
|
|
|
73
|
|
|
353
|
39
|
|
|
|
|
81
|
$success = _clean_eval($make_sub, \%captures); |
|
354
|
39
|
|
|
|
|
134
|
$e = $@; |
|
355
|
|
|
|
|
|
|
} |
|
356
|
39
|
100
|
|
|
|
89
|
unless ($success) { |
|
357
|
2
|
|
|
|
|
8
|
my $space = length($make_sub =~ tr/\n//); |
|
358
|
2
|
|
|
|
|
4
|
my $line = 0; |
|
359
|
2
|
|
|
|
|
8
|
$make_sub =~ s/^/sprintf "%${space}d: ", ++$line/emg; |
|
|
39
|
|
|
|
|
94
|
|
|
360
|
2
|
|
|
|
|
170
|
croak "Eval went very, very wrong:\n\n${make_sub}\n\n$e"; |
|
361
|
|
|
|
|
|
|
} |
|
362
|
37
|
|
|
|
|
202
|
weaken($QUOTED{$$unquoted} = $quoted_info); |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
} |
|
365
|
39
|
|
|
|
|
137
|
$$unquoted; |
|
366
|
|
|
|
|
|
|
} |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub qsub ($) { |
|
369
|
1
|
|
|
2
|
1
|
512
|
goto "e_sub; |
|
370
|
|
|
|
|
|
|
} |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
sub CLONE { |
|
373
|
5
|
|
|
6
|
|
147
|
my @quoted = map { defined $_ ? ( |
|
374
|
2
|
|
|
|
|
5
|
$_->{unquoted} && ${$_->{unquoted}} ? (${ $_->{unquoted} } => $_) : (), |
|
375
|
8
|
100
|
100
|
|
|
23
|
$_->{deferred} ? ($_->{deferred} => $_) : (), |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
) : () } values %QUOTED; |
|
377
|
5
|
|
|
|
|
20
|
%QUOTED = @quoted; |
|
378
|
5
|
|
|
|
|
17
|
weaken($_) for values %QUOTED; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
1; |
|
382
|
|
|
|
|
|
|
__END__ |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=encoding utf-8 |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=head1 NAME |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
Sub::Quote - Efficient generation of subroutines via string eval |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
package Silly; |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
use Sub::Quote qw(quote_sub unquote_sub quoted_from_sub); |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
quote_sub 'Silly::kitty', q{ print "meow" }; |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
quote_sub 'Silly::doggy', q{ print "woof" }; |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
my $sound = 0; |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
quote_sub 'Silly::dagron', |
|
403
|
|
|
|
|
|
|
q{ print ++$sound % 2 ? 'burninate' : 'roar' }, |
|
404
|
|
|
|
|
|
|
{ '$sound' => \$sound }; |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
And elsewhere: |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
Silly->kitty; # meow |
|
409
|
|
|
|
|
|
|
Silly->doggy; # woof |
|
410
|
|
|
|
|
|
|
Silly->dagron; # burninate |
|
411
|
|
|
|
|
|
|
Silly->dagron; # roar |
|
412
|
|
|
|
|
|
|
Silly->dagron; # burninate |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
415
|
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
This package provides performant ways to generate subroutines from strings. |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=head1 SUBROUTINES |
|
419
|
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=head2 quote_sub |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
my $coderef = quote_sub 'Foo::bar', q{ print $x++ . "\n" }, { '$x' => \0 }; |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
Arguments: ?$name, $code, ?\%captures, ?\%options |
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
C<$name> is the subroutine where the coderef will be installed. |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
C<$code> is a string that will be turned into code. |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
C<\%captures> is a hashref of variables that will be made available to the |
|
431
|
|
|
|
|
|
|
code. The keys should be the full name of the variable to be made available, |
|
432
|
|
|
|
|
|
|
including the sigil. The values should be references to the values. The |
|
433
|
|
|
|
|
|
|
variables will contain copies of the values. See the L</SYNOPSIS>'s |
|
434
|
|
|
|
|
|
|
C<Silly::dagron> for an example using captures. |
|
435
|
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
Exported by default. |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=head3 options |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=over 2 |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
=item C<no_install> |
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
B<Boolean>. Set this option to not install the generated coderef into the |
|
445
|
|
|
|
|
|
|
passed subroutine name on undefer. |
|
446
|
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=item C<no_defer> |
|
448
|
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
B<Boolean>. Prevents a Sub::Defer wrapper from being generated for the quoted |
|
450
|
|
|
|
|
|
|
sub. If the sub will most likely be called at some point, setting this is a |
|
451
|
|
|
|
|
|
|
good idea. For a sub that will most likely be inlined, it is not recommended. |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
=item C<package> |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
The package that the quoted sub will be evaluated in. If not specified, the |
|
456
|
|
|
|
|
|
|
package from sub calling C<quote_sub> will be used. |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
=item C<hints> |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
The value of L<< C<$^H> | perlvar/$^H >> to use for the code being evaluated. |
|
461
|
|
|
|
|
|
|
This captures the settings of the L<strict> pragma. If not specified, the value |
|
462
|
|
|
|
|
|
|
from the calling code will be used. |
|
463
|
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
=item C<warning_bits> |
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
The value of L<< C<${^WARNING_BITS}> | perlvar/${^WARNING_BITS} >> to use for |
|
467
|
|
|
|
|
|
|
the code being evaluated. This captures the L<warnings> set. If not specified, |
|
468
|
|
|
|
|
|
|
the warnings from the calling code will be used. |
|
469
|
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
=item C<%^H> |
|
471
|
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
The value of L<< C<%^H> | perlvar/%^H >> to use for the code being evaluated. |
|
473
|
|
|
|
|
|
|
This captures additional pragma settings. If not specified, the value from the |
|
474
|
|
|
|
|
|
|
calling code will be used if possible (on perl 5.10+). |
|
475
|
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
=item C<attributes> |
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
The L<perlsub/Subroutine Attributes> to apply to the sub generated. Should be |
|
479
|
|
|
|
|
|
|
specified as an array reference. The attributes will be applied to both the |
|
480
|
|
|
|
|
|
|
generated sub and the deferred wrapper, if one is used. |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
=item C<file> |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
The apparent filename to use for the code being evaluated. |
|
485
|
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
=item C<line> |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
The apparent line number |
|
489
|
|
|
|
|
|
|
to use for the code being evaluated. |
|
490
|
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
=back |
|
492
|
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=head2 unquote_sub |
|
494
|
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
my $coderef = unquote_sub $sub; |
|
496
|
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
Forcibly replace subroutine with actual code. |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
If $sub is not a quoted sub, this is a no-op. |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Exported by default. |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=head2 quoted_from_sub |
|
504
|
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
my $data = quoted_from_sub $sub; |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
my ($name, $code, $captures, $compiled_sub) = @$data; |
|
508
|
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
Returns original arguments to quote_sub, plus the compiled version if this |
|
510
|
|
|
|
|
|
|
sub has already been unquoted. |
|
511
|
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
Note that $sub can be either the original quoted version or the compiled |
|
513
|
|
|
|
|
|
|
version for convenience. |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
Exported by default. |
|
516
|
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
=head2 inlinify |
|
518
|
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
my $prelude = capture_unroll '$captures', { |
|
520
|
|
|
|
|
|
|
'$x' => 1, |
|
521
|
|
|
|
|
|
|
'$y' => 2, |
|
522
|
|
|
|
|
|
|
}, 4; |
|
523
|
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
my $inlined_code = inlinify q{ |
|
525
|
|
|
|
|
|
|
my ($x, $y) = @_; |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
print $x + $y . "\n"; |
|
528
|
|
|
|
|
|
|
}, '$x, $y', $prelude; |
|
529
|
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
Takes a string of code, a string of arguments, a string of code which acts as a |
|
531
|
|
|
|
|
|
|
"prelude", and a B<Boolean> representing whether or not to localize the |
|
532
|
|
|
|
|
|
|
arguments. |
|
533
|
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
=head2 quotify |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
my $quoted_value = quotify $value; |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
Quotes a single (non-reference) scalar value for use in a code string. The |
|
539
|
|
|
|
|
|
|
result should reproduce the original value, including strings, undef, integers, |
|
540
|
|
|
|
|
|
|
and floating point numbers. The resulting floating point numbers (including |
|
541
|
|
|
|
|
|
|
infinites and not a number) should be precisely equal to the original, if |
|
542
|
|
|
|
|
|
|
possible. The exact format of the resulting number should not be relied on, as |
|
543
|
|
|
|
|
|
|
it may include hex floats or math expressions. |
|
544
|
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
=head2 capture_unroll |
|
546
|
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
my $prelude = capture_unroll '$captures', { |
|
548
|
|
|
|
|
|
|
'$x' => 1, |
|
549
|
|
|
|
|
|
|
'$y' => 2, |
|
550
|
|
|
|
|
|
|
}, 4; |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
Arguments: $from, \%captures, $indent |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
Generates a snippet of code which is suitable to be used as a prelude for |
|
555
|
|
|
|
|
|
|
L</inlinify>. C<$from> is a string will be used as a hashref in the resulting |
|
556
|
|
|
|
|
|
|
code. The keys of C<%captures> are the names of the variables and the values |
|
557
|
|
|
|
|
|
|
are ignored. C<$indent> is the number of spaces to indent the result by. |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=head2 qsub |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
my $hash = { |
|
562
|
|
|
|
|
|
|
coderef => qsub q{ print "hello"; }, |
|
563
|
|
|
|
|
|
|
other => 5, |
|
564
|
|
|
|
|
|
|
}; |
|
565
|
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
Arguments: $code |
|
567
|
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
Works exactly like L</quote_sub>, but includes a prototype to only accept a |
|
569
|
|
|
|
|
|
|
single parameter. This makes it easier to include in hash structures or lists. |
|
570
|
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
Exported by default. |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
=head2 sanitize_identifier |
|
574
|
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
my $var_name = '$variable_for_' . sanitize_identifier('@name'); |
|
576
|
|
|
|
|
|
|
quote_sub qq{ print \$${var_name} }, { $var_name => \$value }; |
|
577
|
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
Arguments: $identifier |
|
579
|
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
Sanitizes a value so that it can be used in an identifier. |
|
581
|
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
=head1 ENVIRONMENT |
|
583
|
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
=head2 SUB_QUOTE_DEBUG |
|
585
|
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
Causes code to be output to C<STDERR> before being evaled. Several forms are |
|
587
|
|
|
|
|
|
|
supported: |
|
588
|
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
=over 4 |
|
590
|
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
=item C<1> |
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
All subs will be output. |
|
594
|
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
=item C</foo/> |
|
596
|
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
Subs will be output if their code matches the given regular expression. |
|
598
|
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
=item C<simple_identifier> |
|
600
|
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
Any sub with the given name will be output. |
|
602
|
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
=item C<Full::identifier> |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
A sub matching the full name will be output. |
|
606
|
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
=item C<Package::Name::> |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
Any sub in the given package (including anonymous subs) will be output. |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
=back |
|
612
|
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
=head1 CAVEATS |
|
614
|
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
Much of this is just string-based code-generation, and as a result, a few |
|
616
|
|
|
|
|
|
|
caveats apply. |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
=head2 return |
|
619
|
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
Calling C<return> from a quote_sub'ed sub will not likely do what you intend. |
|
621
|
|
|
|
|
|
|
Instead of returning from the code you defined in C<quote_sub>, it will return |
|
622
|
|
|
|
|
|
|
from the overall function it is composited into. |
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
So when you pass in: |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
quote_sub q{ return 1 if $condition; $morecode } |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
It might turn up in the intended context as follows: |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
sub foo { |
|
631
|
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
<important code a> |
|
633
|
|
|
|
|
|
|
do { |
|
634
|
|
|
|
|
|
|
return 1 if $condition; |
|
635
|
|
|
|
|
|
|
$morecode |
|
636
|
|
|
|
|
|
|
}; |
|
637
|
|
|
|
|
|
|
<important code b> |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
} |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
Which will obviously return from foo, when all you meant to do was return from |
|
642
|
|
|
|
|
|
|
the code context in quote_sub and proceed with running important code b. |
|
643
|
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=head2 pragmas |
|
645
|
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
C<Sub::Quote> preserves the environment of the code creating the |
|
647
|
|
|
|
|
|
|
quoted subs. This includes the package, strict, warnings, and any |
|
648
|
|
|
|
|
|
|
other lexical pragmas. This is done by prefixing the code with a |
|
649
|
|
|
|
|
|
|
block that sets up a matching environment. When inlining C<Sub::Quote> |
|
650
|
|
|
|
|
|
|
subs, care should be taken that user pragmas won't effect the rest |
|
651
|
|
|
|
|
|
|
of the code. |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
=head1 SUPPORT |
|
654
|
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
Users' IRC: #moose on irc.perl.org |
|
656
|
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
=for :html |
|
658
|
|
|
|
|
|
|
L<(click for instant chatroom login)|http://chat.mibbit.com/#moose@irc.perl.org> |
|
659
|
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
Development and contribution IRC: #web-simple on irc.perl.org |
|
661
|
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
=for :html |
|
663
|
|
|
|
|
|
|
L<(click for instant chatroom login)|http://chat.mibbit.com/#web-simple@irc.perl.org> |
|
664
|
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
Bugtracker: L<https://rt.cpan.org/Public/Dist/Display.html?Name=Sub-Quote> |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
Git repository: L<git://github.com/moose/Sub-Quote.git> |
|
668
|
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
Git browser: L<https://github.com/moose/Sub-Quote> |
|
670
|
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
=head1 AUTHOR |
|
672
|
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk> |
|
674
|
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
=head1 CONTRIBUTORS |
|
676
|
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com> |
|
678
|
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
ribasushi - Peter Rabbitson (cpan:RIBASUSHI) <ribasushi@cpan.org> |
|
680
|
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com> |
|
682
|
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
tobyink - Toby Inkster (cpan:TOBYINK) <tobyink@cpan.org> |
|
684
|
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org> |
|
686
|
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
bluefeet - Aran Deltac (cpan:BLUEFEET) <bluefeet@gmail.com> |
|
688
|
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
ether - Karen Etheridge (cpan:ETHER) <ether@cpan.org> |
|
690
|
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
dolmen - Olivier Mengué (cpan:DOLMEN) <dolmen@cpan.org> |
|
692
|
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
alexbio - Alessandro Ghedini (cpan:ALEXBIO) <alexbio@cpan.org> |
|
694
|
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
getty - Torsten Raudssus (cpan:GETTY) <torsten@raudss.us> |
|
696
|
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
arcanez - Justin Hunter (cpan:ARCANEZ) <justin.d.hunter@gmail.com> |
|
698
|
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
kanashiro - Lucas Kanashiro (cpan:KANASHIRO) <kanashiro.duarte@gmail.com> |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
djerius - Diab Jerius (cpan:DJERIUS) <djerius@cfa.harvard.edu> |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
704
|
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
Copyright (c) 2010-2016 the Sub::Quote L</AUTHOR> and L</CONTRIBUTORS> |
|
706
|
|
|
|
|
|
|
as listed above. |
|
707
|
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
=head1 LICENSE |
|
709
|
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
This library is free software and may be distributed under the same terms |
|
711
|
|
|
|
|
|
|
as perl itself. See L<http://dev.perl.org/licenses/>. |
|
712
|
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
=cut |