line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Template::Alloy::Operator; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Template::Alloy::Operator - Operator role. |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=cut |
8
|
|
|
|
|
|
|
|
9
|
10
|
|
|
10
|
|
71
|
use strict; |
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
324
|
|
10
|
10
|
|
|
10
|
|
54
|
use warnings; |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
335
|
|
11
|
10
|
|
|
10
|
|
66
|
use Template::Alloy; |
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
327
|
|
12
|
10
|
|
|
10
|
|
63
|
use base qw(Exporter); |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
2358
|
|
13
|
|
|
|
|
|
|
our @EXPORT_OK = qw(play_operator define_operator |
14
|
|
|
|
|
|
|
$QR_OP $QR_OP_ASSIGN $QR_OP_PREFIX $QR_PRIVATE |
15
|
|
|
|
|
|
|
$OP $OP_ASSIGN $OP_PREFIX $OP_POSTFIX $OP_DISPATCH); |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = $Template::Alloy::VERSION; |
18
|
|
|
|
|
|
|
|
19
|
0
|
|
|
0
|
0
|
0
|
sub new { die "This class is a role for use by packages such as Template::Alloy" } |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
### setup the operator parsing |
24
|
|
|
|
|
|
|
our $OPERATORS = [ |
25
|
|
|
|
|
|
|
# type precedence symbols action (undef means play_operator will handle) |
26
|
|
|
|
|
|
|
['prefix', 99, ['\\'], undef], |
27
|
|
|
|
|
|
|
['postfix', 98, ['++'], undef], |
28
|
|
|
|
|
|
|
['postfix', 98, ['--'], undef], |
29
|
|
|
|
|
|
|
['prefix', 97, ['++'], undef], |
30
|
|
|
|
|
|
|
['prefix', 97, ['--'], undef], |
31
|
10
|
|
|
10
|
|
76
|
['right', 96, ['**', 'pow'], sub { no warnings; $_[0] ** $_[1] } ], |
|
10
|
|
|
|
|
27
|
|
|
10
|
|
|
|
|
842
|
|
32
|
10
|
|
|
10
|
|
80
|
['prefix', 93, ['!'], sub { no warnings; ! $_[0] } ], |
|
10
|
|
|
|
|
23
|
|
|
10
|
|
|
|
|
822
|
|
33
|
10
|
|
|
10
|
|
75
|
['prefix', 93, ['-'], sub { no warnings; @_ == 1 ? 0 - $_[0] : $_[0] - $_[1] } ], |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
737
|
|
34
|
10
|
|
|
10
|
|
65
|
['left', 90, ['*'], sub { no warnings; $_[0] * $_[1] } ], |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
781
|
|
35
|
10
|
|
|
10
|
|
70
|
['left', 90, ['/'], sub { no warnings; $_[0] / $_[1] } ], |
|
10
|
|
|
|
|
41
|
|
|
10
|
|
|
|
|
632
|
|
36
|
10
|
|
|
10
|
|
84
|
['left', 90, ['div', 'DIV'], sub { no warnings; int($_[0] / $_[1]) } ], |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
643
|
|
37
|
10
|
|
|
10
|
|
62
|
['left', 90, ['%', 'mod', 'MOD'], sub { no warnings; $_[0] % $_[1] } ], |
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
583
|
|
38
|
10
|
|
|
10
|
|
65
|
['left', 85, ['+'], sub { no warnings; $_[0] + $_[1] } ], |
|
10
|
|
|
|
|
16
|
|
|
10
|
|
|
|
|
674
|
|
39
|
10
|
|
|
10
|
|
64
|
['left', 85, ['-'], sub { no warnings; @_ == 1 ? 0 - $_[0] : $_[0] - $_[1] } ], |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
782
|
|
40
|
|
|
|
|
|
|
['left', 85, ['~', '_'], undef], |
41
|
10
|
|
|
10
|
|
71
|
['none', 80, ['<'], sub { no warnings; $_[0] < $_[1] } ], |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
645
|
|
42
|
10
|
|
|
10
|
|
62
|
['none', 80, ['>'], sub { no warnings; $_[0] > $_[1] } ], |
|
10
|
|
|
|
|
27
|
|
|
10
|
|
|
|
|
563
|
|
43
|
10
|
|
|
10
|
|
60
|
['none', 80, ['<='], sub { no warnings; $_[0] <= $_[1] } ], |
|
10
|
|
|
|
|
36
|
|
|
10
|
|
|
|
|
567
|
|
44
|
10
|
|
|
10
|
|
78
|
['none', 80, ['>='], sub { no warnings; $_[0] >= $_[1] } ], |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
586
|
|
45
|
10
|
|
|
10
|
|
70
|
['none', 80, ['lt'], sub { no warnings; $_[0] lt $_[1] } ], |
|
10
|
|
|
|
|
26
|
|
|
10
|
|
|
|
|
596
|
|
46
|
10
|
|
|
10
|
|
62
|
['none', 80, ['gt'], sub { no warnings; $_[0] gt $_[1] } ], |
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
849
|
|
47
|
10
|
|
|
10
|
|
124
|
['none', 80, ['le'], sub { no warnings; $_[0] le $_[1] } ], |
|
10
|
|
|
|
|
26
|
|
|
10
|
|
|
|
|
609
|
|
48
|
10
|
|
|
10
|
|
67
|
['none', 80, ['ge'], sub { no warnings; $_[0] ge $_[1] } ], |
|
10
|
|
|
|
|
33
|
|
|
10
|
|
|
|
|
658
|
|
49
|
10
|
|
|
10
|
|
83
|
['none', 75, ['=='], sub { no warnings; $_[0] == $_[1] } ], |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
683
|
|
50
|
10
|
|
|
10
|
|
64
|
['none', 75, ['eq'], sub { no warnings; $_[0] eq $_[1] } ], |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
596
|
|
51
|
10
|
|
|
10
|
|
62
|
['none', 75, ['!='], sub { no warnings; $_[0] != $_[1] } ], |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
655
|
|
52
|
10
|
|
|
10
|
|
64
|
['none', 75, ['ne'], sub { no warnings; $_[0] ne $_[1] } ], |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
595
|
|
53
|
10
|
|
|
10
|
|
69
|
['none', 75, ['<=>'], sub { no warnings; $_[0] <=> $_[1] } ], |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
674
|
|
54
|
10
|
|
|
10
|
|
73
|
['none', 75, ['cmp'], sub { no warnings; $_[0] cmp $_[1] } ], |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
751
|
|
55
|
|
|
|
|
|
|
['left', 70, ['&&'], undef], |
56
|
|
|
|
|
|
|
['right', 65, ['||'], undef], |
57
|
|
|
|
|
|
|
['right', 65, ['//'], undef], |
58
|
10
|
|
|
10
|
|
65
|
['none', 60, ['..'], sub { no warnings; $_[0] .. $_[1] } ], |
|
10
|
|
|
|
|
33
|
|
|
10
|
|
|
|
|
1072
|
|
59
|
|
|
|
|
|
|
['ternary', 55, ['?', ':'], undef], |
60
|
|
|
|
|
|
|
['assign', 53, ['+='], undef], |
61
|
|
|
|
|
|
|
['assign', 53, ['-='], undef], |
62
|
|
|
|
|
|
|
['assign', 53, ['*='], undef], |
63
|
|
|
|
|
|
|
['assign', 53, ['/='], undef], |
64
|
|
|
|
|
|
|
['assign', 53, ['%='], undef], |
65
|
|
|
|
|
|
|
['assign', 53, ['**='], undef], |
66
|
|
|
|
|
|
|
['assign', 53, ['~=', '_='], undef], |
67
|
|
|
|
|
|
|
['assign', 53, ['//='], undef], |
68
|
|
|
|
|
|
|
['assign', 53, ['||='], undef], |
69
|
|
|
|
|
|
|
['assign', 52, ['='], undef], |
70
|
10
|
|
|
10
|
|
64
|
['prefix', 50, ['not', 'NOT'], sub { no warnings; ! $_[0] } ], |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
12120
|
|
71
|
|
|
|
|
|
|
['left', 45, ['and', 'AND'], undef], |
72
|
|
|
|
|
|
|
['right', 40, ['or', 'OR' ], undef], |
73
|
|
|
|
|
|
|
['right', 40, ['err', 'ERR'], undef], |
74
|
|
|
|
|
|
|
]; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
our ($QR_OP, $QR_OP_PREFIX, $QR_OP_ASSIGN, $OP, $OP_PREFIX, $OP_DISPATCH, $OP_ASSIGN, $OP_POSTFIX, $OP_TERNARY); |
77
|
|
|
|
|
|
|
_build_ops(); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub _op_qr { # no mixed \w\W operators |
82
|
30
|
|
|
30
|
|
53
|
my %used; |
83
|
30
|
|
|
|
|
56
|
my $chrs = join '|', reverse sort map {quotemeta $_} grep {++$used{$_} < 2} grep {! /\{\}|\[\]/} grep {/^\W{2,}$/} @_; |
|
320
|
|
|
|
|
657
|
|
|
320
|
|
|
|
|
680
|
|
|
320
|
|
|
|
|
629
|
|
|
700
|
|
|
|
|
1447
|
|
84
|
30
|
|
|
|
|
89
|
my $chr = join '', sort map {quotemeta $_} grep {++$used{$_} < 2} grep {/^\W$/} @_; |
|
150
|
|
|
|
|
322
|
|
|
150
|
|
|
|
|
413
|
|
|
700
|
|
|
|
|
1296
|
|
85
|
30
|
|
|
|
|
71
|
my $word = join '|', reverse sort grep {++$used{$_} < 2} grep {/^\w+$/} @_; |
|
210
|
|
|
|
|
602
|
|
|
700
|
|
|
|
|
1351
|
|
86
|
30
|
50
|
|
|
|
449
|
$chr = "[$chr]" if $chr; |
87
|
30
|
100
|
|
|
|
97
|
$word = "\\b(?:$word)\\b" if $word; |
88
|
30
|
|
50
|
|
|
55
|
return join('|', grep {length} $chrs, $chr, $word) || die "Missing operator regex"; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub _build_ops { |
92
|
10
|
|
|
10
|
|
32
|
$QR_OP = _op_qr(map {@{ $_->[2] }} grep {$_->[0] ne 'prefix'} @$OPERATORS); |
|
420
|
|
|
|
|
514
|
|
|
420
|
|
|
|
|
681
|
|
|
480
|
|
|
|
|
772
|
|
93
|
10
|
|
|
|
|
60
|
$QR_OP_PREFIX = _op_qr(map {@{ $_->[2] }} grep {$_->[0] eq 'prefix'} @$OPERATORS); |
|
60
|
|
|
|
|
82
|
|
|
60
|
|
|
|
|
120
|
|
|
480
|
|
|
|
|
760
|
|
94
|
10
|
|
|
|
|
29
|
$QR_OP_ASSIGN = _op_qr(map {@{ $_->[2] }} grep {$_->[0] eq 'assign'} @$OPERATORS); |
|
100
|
|
|
|
|
128
|
|
|
100
|
|
|
|
|
176
|
|
|
480
|
|
|
|
|
768
|
|
95
|
10
|
|
|
|
|
32
|
$OP = {map {my $ref = $_; map {$_ => $ref} @{$ref->[2]}} grep {$_->[0] ne 'prefix' } @$OPERATORS}; # all non-prefix |
|
420
|
|
|
|
|
536
|
|
|
420
|
|
|
|
|
537
|
|
|
520
|
|
|
|
|
1162
|
|
|
420
|
|
|
|
|
586
|
|
|
480
|
|
|
|
|
748
|
|
96
|
10
|
|
|
|
|
67
|
$OP_PREFIX = {map {my $ref = $_; map {$_ => $ref} @{$ref->[2]}} grep {$_->[0] eq 'prefix' } @$OPERATORS}; |
|
60
|
|
|
|
|
91
|
|
|
60
|
|
|
|
|
415
|
|
|
70
|
|
|
|
|
164
|
|
|
60
|
|
|
|
|
121
|
|
|
480
|
|
|
|
|
783
|
|
97
|
10
|
|
|
|
|
29
|
$OP_DISPATCH = {map {my $ref = $_; map {$_ => $ref->[3]} @{$ref->[2]}} grep {$_->[3] } @$OPERATORS}; |
|
250
|
|
|
|
|
324
|
|
|
250
|
|
|
|
|
301
|
|
|
300
|
|
|
|
|
649
|
|
|
250
|
|
|
|
|
350
|
|
|
480
|
|
|
|
|
644
|
|
98
|
10
|
|
|
|
|
72
|
$OP_ASSIGN = {map {my $ref = $_; map {$_ => 1} @{$ref->[2]}} grep {$_->[0] eq 'assign' } @$OPERATORS}; |
|
100
|
|
|
|
|
136
|
|
|
100
|
|
|
|
|
121
|
|
|
110
|
|
|
|
|
220
|
|
|
100
|
|
|
|
|
146
|
|
|
480
|
|
|
|
|
748
|
|
99
|
10
|
|
|
|
|
33
|
$OP_POSTFIX = {map {my $ref = $_; map {$_ => 1} @{$ref->[2]}} grep {$_->[0] eq 'postfix'} @$OPERATORS}; # bool is postfix |
|
20
|
|
|
|
|
37
|
|
|
20
|
|
|
|
|
28
|
|
|
20
|
|
|
|
|
84
|
|
|
20
|
|
|
|
|
61
|
|
|
480
|
|
|
|
|
762
|
|
100
|
10
|
|
|
|
|
76
|
$OP_TERNARY = {map {my $ref = $_; map {$_ => 1} @{$ref->[2]}} grep {$_->[0] eq 'ternary'} @$OPERATORS}; # bool is ternary |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
18
|
|
|
20
|
|
|
|
|
83
|
|
|
10
|
|
|
|
|
19
|
|
|
480
|
|
|
|
|
813
|
|
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub play_operator { |
106
|
9014
|
|
|
9014
|
1
|
17032
|
my ($self, $tree) = @_; |
107
|
|
|
|
|
|
|
### $tree looks like [undef, '+', 4, 5] |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
return $OP_DISPATCH->{$tree->[1]}->(@$tree == 3 ? $self->play_expr($tree->[2]) : ($self->play_expr($tree->[2]), $self->play_expr($tree->[3]))) |
110
|
9014
|
100
|
|
|
|
27515
|
if $OP_DISPATCH->{$tree->[1]}; |
|
|
100
|
|
|
|
|
|
111
|
|
|
|
|
|
|
|
112
|
5025
|
|
|
|
|
8649
|
my $op = $tree->[1]; |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
### do custom and short-circuitable operators |
115
|
5025
|
100
|
100
|
|
|
31371
|
if ($op eq '=') { |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
116
|
3192
|
|
|
|
|
7089
|
my $val = $self->play_expr($tree->[3]); |
117
|
3192
|
|
|
|
|
9328
|
$self->set_variable($tree->[2], $val); |
118
|
3192
|
|
|
|
|
7862
|
return $val; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
} elsif ($op eq '||' || $op eq 'or' || $op eq 'OR') { |
121
|
115
|
|
100
|
|
|
392
|
my $val = $self->play_expr($tree->[2]) || $self->play_expr($tree->[3]); |
122
|
115
|
50
|
|
|
|
431
|
return defined($val) ? $val : ''; |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
} elsif ($op eq '&&' || $op eq 'and' || $op eq 'AND') { |
125
|
15
|
|
66
|
|
|
53
|
my $val = $self->play_expr($tree->[2]) && $self->play_expr($tree->[3]); |
126
|
15
|
50
|
|
|
|
52
|
return defined($val) ? $val : ''; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
} elsif ($op eq '//' || $op eq 'err' || $op eq 'ERR') { |
129
|
234
|
|
|
|
|
626
|
my $val = $self->play_expr($tree->[2]); |
130
|
234
|
100
|
|
|
|
811
|
return $val if defined $val; |
131
|
50
|
|
|
|
|
152
|
return $self->play_expr($tree->[3]); |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
} elsif ($op eq '?') { |
134
|
10
|
|
|
10
|
|
87
|
no warnings; |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
754
|
|
135
|
63
|
100
|
|
|
|
182
|
return $self->play_expr($tree->[2]) ? $self->play_expr($tree->[3]) : $self->play_expr($tree->[4]); |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
} elsif ($op eq '~' || $op eq '_') { |
138
|
10
|
|
|
10
|
|
63
|
no warnings; |
|
10
|
|
|
|
|
27
|
|
|
10
|
|
|
|
|
1092
|
|
139
|
222
|
|
|
|
|
473
|
my $s = ''; |
140
|
222
|
|
|
|
|
1138
|
$s .= $self->play_expr($tree->[$_]) for 2 .. $#$tree; |
141
|
222
|
|
|
|
|
777
|
return $s; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
} elsif ($op eq '[]') { |
144
|
321
|
|
|
|
|
1052
|
return [map {$self->play_expr($tree->[$_])} 2 .. $#$tree]; |
|
466
|
|
|
|
|
1225
|
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
} elsif ($op eq '{}') { |
147
|
10
|
|
|
10
|
|
77
|
no warnings; |
|
10
|
|
|
|
|
23
|
|
|
10
|
|
|
|
|
733
|
|
148
|
635
|
|
|
|
|
1104
|
my @e; |
149
|
635
|
|
|
|
|
3051
|
push @e, $self->play_expr($tree->[$_]) for 2 .. $#$tree; |
150
|
635
|
|
|
|
|
2816
|
return {@e}; |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
} elsif ($op eq '++') { |
153
|
10
|
|
|
10
|
|
66
|
no warnings; |
|
10
|
|
|
|
|
28
|
|
|
10
|
|
|
|
|
716
|
|
154
|
15
|
|
|
|
|
51
|
my $val = 0 + $self->play_expr($tree->[2]); |
155
|
15
|
|
|
|
|
67
|
$self->set_variable($tree->[2], $val + 1); |
156
|
15
|
100
|
|
|
|
63
|
return $tree->[3] ? $val : $val + 1; # ->[3] is set to 1 during parsing of postfix ops |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
} elsif ($op eq '--') { |
159
|
10
|
|
|
10
|
|
61
|
no warnings; |
|
10
|
|
|
|
|
23
|
|
|
10
|
|
|
|
|
6962
|
|
160
|
15
|
|
|
|
|
48
|
my $val = 0 + $self->play_expr($tree->[2]); |
161
|
15
|
|
|
|
|
63
|
$self->set_variable($tree->[2], $val - 1); |
162
|
15
|
100
|
|
|
|
65
|
return $tree->[3] ? $val : $val - 1; # ->[3] is set to 1 during parsing of postfix ops |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
} elsif ($op eq '@()') { |
165
|
45
|
|
|
|
|
117
|
local $self->{'CALL_CONTEXT'} = 'list'; |
166
|
45
|
|
|
|
|
144
|
return $self->play_expr($tree->[2]); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
} elsif ($op eq '$()') { |
169
|
45
|
|
|
|
|
132
|
local $self->{'CALL_CONTEXT'} = 'item'; |
170
|
45
|
|
|
|
|
136
|
return $self->play_expr($tree->[2]); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
} elsif ($op eq '\\') { |
173
|
54
|
|
|
|
|
103
|
my $var = $tree->[2]; |
174
|
|
|
|
|
|
|
|
175
|
54
|
|
|
|
|
242
|
my $ref = $self->play_expr($var, {return_ref => 1}); |
176
|
54
|
100
|
|
|
|
191
|
return $ref if ! ref $ref; |
177
|
42
|
100
|
66
|
27
|
|
287
|
return sub { sub { $$ref } } if ref $ref eq 'SCALAR' || ref $ref eq 'REF'; |
|
27
|
|
|
|
|
111
|
|
|
27
|
|
|
|
|
76
|
|
178
|
|
|
|
|
|
|
|
179
|
15
|
|
|
|
|
28
|
my $self_copy = $self; |
180
|
15
|
|
|
|
|
29
|
eval {require Scalar::Util; Scalar::Util::weaken($self_copy)}; |
|
15
|
|
|
|
|
87
|
|
|
15
|
|
|
|
|
56
|
|
181
|
|
|
|
|
|
|
|
182
|
15
|
100
|
|
|
|
52
|
my $last = ['temp deref key', $var->[-1] ? [@{ $var->[-1] }] : 0]; |
|
6
|
|
|
|
|
20
|
|
183
|
|
|
|
|
|
|
return sub { sub { # return a double sub so that the current play_expr will return a coderef |
184
|
12
|
|
|
|
|
38
|
local $self_copy->{'_vars'}->{'temp deref key'} = $ref; |
185
|
12
|
100
|
|
|
|
43
|
$last->[-1] = (ref $last->[-1] ? [@{ $last->[-1] }, @_] : [@_]) if @_; |
|
3
|
100
|
|
|
|
9
|
|
186
|
12
|
|
|
|
|
38
|
return $self->play_expr($last); |
187
|
15
|
|
|
15
|
|
110
|
} }; |
|
15
|
|
|
|
|
82
|
|
188
|
|
|
|
|
|
|
} elsif ($op eq '->') { |
189
|
27
|
|
|
|
|
121
|
my $code = $self->_macro_sub($tree->[2], $tree->[3]); |
190
|
27
|
|
|
27
|
|
157
|
return sub { $code }; # do the double sub dance |
|
27
|
|
|
|
|
74
|
|
191
|
|
|
|
|
|
|
} elsif ($op eq 'qr') { |
192
|
27
|
100
|
|
|
|
484
|
return $tree->[3] ? qr{(?$tree->[3]:$tree->[2])} : qr{$tree->[2]}; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
|
$self->throw('operator', "Un-implemented operation $op"); |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub define_operator { |
201
|
0
|
|
|
0
|
1
|
|
my ($self, $args) = @_; |
202
|
0
|
|
|
|
|
|
push @$OPERATORS, [@{ $args }{qw(type precedence symbols play_sub)}]; |
|
0
|
|
|
|
|
|
|
203
|
0
|
|
|
|
|
|
_build_ops(); |
204
|
0
|
|
|
|
|
|
return 1; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
1; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
__END__ |