| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# This file provides a class that parses the Code -member |
|
2
|
|
|
|
|
|
|
# of the PDL::PP code. |
|
3
|
|
|
|
|
|
|
# |
|
4
|
|
|
|
|
|
|
# This is what makes the nice loops go around etc. |
|
5
|
|
|
|
|
|
|
# |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
8
|
|
|
|
|
|
|
PDL::PP::Code; |
|
9
|
|
|
|
|
|
|
|
|
10
|
3
|
|
|
3
|
|
21
|
use strict; |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
121
|
|
|
11
|
3
|
|
|
3
|
|
15
|
use warnings; |
|
|
3
|
|
|
|
|
38
|
|
|
|
3
|
|
|
|
|
208
|
|
|
12
|
3
|
|
|
3
|
|
19
|
use Carp; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
20923
|
|
|
13
|
|
|
|
|
|
|
|
|
14
|
95
|
|
|
95
|
|
107
|
sub get_pdls { @{$_[0]}{qw(ParNames ParObjs)} } |
|
|
95
|
|
|
|
|
196
|
|
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
my @code_args_always = qw(BadFlag SignatureObj GenericTypes ExtraGenericSwitches HaveBroadcasting Name); |
|
17
|
|
|
|
|
|
|
sub make_args { |
|
18
|
9
|
|
|
9
|
|
19
|
my ($target) = @_; |
|
19
|
9
|
|
|
|
|
151
|
("${target}CodeParsed", ["${target}CodeUnparsed","Bad${target}CodeUnparsed?",@code_args_always]); |
|
20
|
|
|
|
|
|
|
} |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Do the appropriate substitutions in the code. |
|
23
|
|
|
|
|
|
|
sub new { |
|
24
|
10
|
|
|
10
|
|
48
|
my($class,$code,$badcode, |
|
25
|
|
|
|
|
|
|
$handlebad, $sig,$generictypes,$extrageneric,$havebroadcasting,$name, |
|
26
|
|
|
|
|
|
|
$dont_add_brcloop, $backcode, $nulldatacheck) = @_; |
|
27
|
10
|
|
|
|
|
48
|
my $parnames = $sig->names_sorted; |
|
28
|
10
|
|
|
|
|
48
|
$handlebad = !!$handlebad; |
|
29
|
|
|
|
|
|
|
|
|
30
|
10
|
50
|
|
|
|
36
|
confess "Error: missing name argument to PDL::PP::Code->new call!\n" |
|
31
|
|
|
|
|
|
|
unless defined $name; |
|
32
|
|
|
|
|
|
|
confess "Error: empty or undefined GenericTypes!\n" |
|
33
|
10
|
50
|
|
|
|
11
|
unless @{$generictypes || []}; |
|
|
10
|
50
|
|
|
|
52
|
|
|
34
|
|
|
|
|
|
|
|
|
35
|
10
|
50
|
0
|
|
|
25
|
$badcode //= $code if $handlebad; |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# last two arguments may not be supplied |
|
38
|
|
|
|
|
|
|
# |
|
39
|
|
|
|
|
|
|
# "backcode" is a flag to the PDL::PP::Broadcastloop class indicating the broadcastloop |
|
40
|
|
|
|
|
|
|
# is for writeback code (typically used for writeback of data from child to parent PDL |
|
41
|
|
|
|
|
|
|
|
|
42
|
10
|
|
33
|
|
|
52
|
$dont_add_brcloop ||= !$havebroadcasting; # two have identical (though inverted) meaning so only track one |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# C++ style comments |
|
45
|
|
|
|
|
|
|
# |
|
46
|
|
|
|
|
|
|
# This regexp isn't perfect because it doesn't cope with |
|
47
|
|
|
|
|
|
|
# literal string constants. |
|
48
|
|
|
|
|
|
|
# |
|
49
|
10
|
|
|
|
|
24
|
$code =~ s,//.*?\n,,g; |
|
50
|
|
|
|
|
|
|
|
|
51
|
10
|
50
|
|
|
|
32
|
if ($::PP_VERBOSE) { |
|
52
|
0
|
|
|
|
|
0
|
print "Processing code for $name\n"; |
|
53
|
0
|
0
|
|
|
|
0
|
print "DONT_ADD_BRCLOOP!\n" if $dont_add_brcloop; |
|
54
|
0
|
|
|
|
|
0
|
print "EXTRAGEN: {" . |
|
55
|
|
|
|
|
|
|
join(" ", |
|
56
|
|
|
|
|
|
|
map "$_=>$$extrageneric{$_}", sort keys %$extrageneric) |
|
57
|
|
|
|
|
|
|
. "}\n"; |
|
58
|
0
|
|
|
|
|
0
|
print "ParNAMES: ",(join ',',@$parnames),"\n"; |
|
59
|
0
|
|
|
|
|
0
|
print "GENTYPES: ", @$generictypes, "\n"; |
|
60
|
0
|
|
|
|
|
0
|
print "HandleBad: $handlebad\n"; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
10
|
|
|
|
|
42
|
my $this = bless { |
|
63
|
|
|
|
|
|
|
IndObjs => $sig->dims_obj, |
|
64
|
|
|
|
|
|
|
ParNames => $parnames, |
|
65
|
|
|
|
|
|
|
ParObjs => $sig->objs, |
|
66
|
|
|
|
|
|
|
Sig => $sig, |
|
67
|
|
|
|
|
|
|
Gencurtype => [], # stack to hold GenType in generic switches |
|
68
|
|
|
|
|
|
|
ftypes_vars => {}, |
|
69
|
|
|
|
|
|
|
ftypes_type => undef, |
|
70
|
|
|
|
|
|
|
Generictypes => $generictypes, # so that MacroAccess can check it |
|
71
|
|
|
|
|
|
|
Name => $name, |
|
72
|
|
|
|
|
|
|
NullDataCheck => $nulldatacheck, |
|
73
|
|
|
|
|
|
|
BadFlag => $handlebad, |
|
74
|
|
|
|
|
|
|
}, $class; |
|
75
|
|
|
|
|
|
|
|
|
76
|
10
|
|
|
|
|
29
|
my @codes = $code; |
|
77
|
10
|
0
|
0
|
|
|
33
|
push @codes, $badcode if $handlebad && ($code ne $badcode || $badcode =~ /PDL_BAD_CODE|PDL_IF_BAD/); |
|
|
|
|
33
|
|
|
|
|
|
78
|
10
|
|
|
|
|
21
|
my (@coderefs, @sizeprivs); |
|
79
|
10
|
|
|
|
|
22
|
for my $c (@codes) { |
|
80
|
|
|
|
|
|
|
# First, separate the code into an array of C fragments (strings), |
|
81
|
|
|
|
|
|
|
# variable references (strings starting with $) and |
|
82
|
|
|
|
|
|
|
# loops (array references, 1. item = variable. |
|
83
|
10
|
|
|
|
|
48
|
my ( $broadcastloops, $coderef, $sizeprivs ) = |
|
84
|
|
|
|
|
|
|
$this->separate_code( "{$c}" ); |
|
85
|
|
|
|
|
|
|
# Now, if there is no explicit broadcastlooping in the code, |
|
86
|
|
|
|
|
|
|
# enclose everything into it. |
|
87
|
9
|
50
|
66
|
|
|
50
|
if(!$broadcastloops && !$dont_add_brcloop) { |
|
88
|
8
|
50
|
|
|
|
19
|
print "Adding broadcastloop...\n" if $::PP_VERBOSE; |
|
89
|
8
|
50
|
|
|
|
64
|
$coderef = $coderef->enter(('PDL::PP::'.($backcode ? 'BackCode' : '').'BroadcastLoop')->new); |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
# Enclose it all in a generic switch. |
|
92
|
9
|
|
50
|
|
|
53
|
my $if_gentype = ($code.($badcode//'')) =~ /PDL_IF_GENTYPE_/; |
|
93
|
|
|
|
|
|
|
$coderef = $coderef->enter(PDL::PP::GenericSwitch->new($generictypes, undef, |
|
94
|
9
|
|
|
|
|
44
|
[grep {!$extrageneric->{$_}} @$parnames],'$PRIV(__datatype)',$if_gentype)); |
|
|
16
|
|
|
|
|
90
|
|
|
95
|
|
|
|
|
|
|
# Do we have extra generic switches? |
|
96
|
|
|
|
|
|
|
# If we do, first reverse the hash: |
|
97
|
9
|
|
|
|
|
20
|
my %glh; |
|
98
|
9
|
|
|
|
|
31
|
push @{$glh{$extrageneric->{$_}}},$_ for sort keys %$extrageneric; |
|
|
0
|
|
|
|
|
0
|
|
|
99
|
9
|
|
|
|
|
19
|
my $no = 0; |
|
100
|
|
|
|
|
|
|
$coderef = $coderef->enter(PDL::PP::GenericSwitch->new($generictypes,$no++, |
|
101
|
9
|
|
|
|
|
26
|
$glh{$_},$_,$if_gentype)) for sort keys %glh; |
|
102
|
9
|
|
|
|
|
17
|
push @coderefs, $coderef; |
|
103
|
9
|
|
|
|
|
22
|
push @sizeprivs, $sizeprivs; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
9
|
50
|
|
|
|
92
|
amalgamate_sizeprivs(@sizeprivs) if @sizeprivs > 1; |
|
106
|
9
|
|
|
|
|
16
|
my $sizeprivs = $sizeprivs[0]; |
|
107
|
9
|
|
|
|
|
46
|
my $coderef = PDL::PP::BadSwitch->new( @coderefs ); |
|
108
|
9
|
50
|
|
|
|
24
|
print "SIZEPRIVSX: ",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
|
109
|
|
|
|
|
|
|
|
|
110
|
9
|
|
|
|
|
34
|
my $pobjs = $sig->objs; |
|
111
|
|
|
|
|
|
|
# Then, in this form, put it together what we want the code to actually do. |
|
112
|
9
|
50
|
|
|
|
22
|
print "SIZEPRIVS: ",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
|
113
|
|
|
|
|
|
|
$this->{Code} = (join '',sort values %$sizeprivs). |
|
114
|
|
|
|
|
|
|
($dont_add_brcloop?'':join '', map "$_\n", |
|
115
|
|
|
|
|
|
|
'if (!$PRIV(broadcast).incs) $CROAK("broadcast.incs NULL");', |
|
116
|
|
|
|
|
|
|
'/* broadcastloop declarations */', |
|
117
|
|
|
|
|
|
|
'int __brcloopval;', |
|
118
|
|
|
|
|
|
|
'register PDL_Indx __tind0,__tind1; /* counters along dim */', |
|
119
|
|
|
|
|
|
|
'register PDL_Indx __tnpdls = $PRIV(broadcast).npdls;', |
|
120
|
|
|
|
|
|
|
'/* dims here are how many steps along those dims */', |
|
121
|
|
|
|
|
|
|
(map "register PDL_Indx __tinc0_$parnames->[$_] = PDL_BRC_INC(\$PRIV(broadcast).incs,__tnpdls,$_,0);", 0..$#$parnames), |
|
122
|
|
|
|
|
|
|
(map "register PDL_Indx __tinc1_$parnames->[$_] = PDL_BRC_INC(\$PRIV(broadcast).incs,__tnpdls,$_,1);", 0..$#$parnames), |
|
123
|
|
|
|
|
|
|
eol_protect( |
|
124
|
|
|
|
|
|
|
"#define ".$this->broadcastloop_macroname($backcode, 'START') . " " . |
|
125
|
|
|
|
|
|
|
$this->broadcastloop_start($this->func_name($backcode)) |
|
126
|
|
|
|
|
|
|
), |
|
127
|
|
|
|
|
|
|
eol_protect( |
|
128
|
|
|
|
|
|
|
"#define ".$this->broadcastloop_macroname($backcode, 'END') . " " . |
|
129
|
|
|
|
|
|
|
$this->broadcastloop_end |
|
130
|
|
|
|
|
|
|
), |
|
131
|
9
|
50
|
|
|
|
138
|
(grep $_, map $_->get_incregisters, @$pobjs{sort keys %$pobjs}), |
|
132
|
|
|
|
|
|
|
). |
|
133
|
|
|
|
|
|
|
$this->params_declare. |
|
134
|
|
|
|
|
|
|
$coderef->get_str($this,[]) |
|
135
|
|
|
|
|
|
|
; |
|
136
|
7
|
|
|
|
|
192
|
$this->{Code}; |
|
137
|
|
|
|
|
|
|
} # new |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# amalgamate sizeprivs from Code/BadCode segments |
|
140
|
|
|
|
|
|
|
# (sizeprivs is a simple hash, with each element |
|
141
|
|
|
|
|
|
|
# containing a string - see PDL::PP::Loop) |
|
142
|
|
|
|
|
|
|
sub amalgamate_sizeprivs { |
|
143
|
0
|
|
|
0
|
|
0
|
my ($sizeprivs, $bad_sizeprivs) = @_; |
|
144
|
0
|
|
|
|
|
0
|
while ( my ( $bad_key, $bad_str ) = each %$bad_sizeprivs ) { |
|
145
|
0
|
|
|
|
|
0
|
my $str = $$sizeprivs{$bad_key}; |
|
146
|
0
|
0
|
0
|
|
|
0
|
die "ERROR: sizeprivs problem in PP/PDLCode.pm (BadVal stuff)\n" |
|
147
|
|
|
|
|
|
|
if defined $str and $str ne $bad_str; |
|
148
|
0
|
|
|
|
|
0
|
$$sizeprivs{$bad_key} = $bad_str; # copy over |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
} |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub eol_protect { |
|
153
|
18
|
|
|
18
|
|
34
|
my ($text) = @_; |
|
154
|
18
|
|
|
|
|
370
|
join " \\\n", grep /\S/, split /\n/, $text; |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
sub params_declare { |
|
158
|
9
|
|
|
9
|
|
20
|
my ($this) = @_; |
|
159
|
9
|
|
|
|
|
23
|
my ($ord,$pdls) = $this->get_pdls; |
|
160
|
9
|
|
|
|
|
56
|
my %istyped = map +($_=>1), grep $pdls->{$_}{FlagTypeOverride}, @$ord; |
|
161
|
|
|
|
|
|
|
my @decls = map $_->get_xsdatapdecl($istyped{$_->name} ? "PDL_TYPE_PARAM_".$_->name : "PDL_TYPE_OP", $this->{NullDataCheck}, $istyped{$_->name} ? "PDL_PPSYM_PARAM_".$_->name : "PDL_PPSYM_OP", $this->{BadFlag}), |
|
162
|
9
|
100
|
|
|
|
54
|
map $pdls->{$_}, @$ord; |
|
|
|
100
|
|
|
|
|
|
|
163
|
9
|
|
|
|
|
48
|
my @param_names = ("PDL_TYPE_OP", "PDL_PPSYM_OP", map +("PDL_TYPE_PARAM_$_","PDL_PPSYM_PARAM_$_"), grep $istyped{$_}, @$ord); |
|
164
|
9
|
|
|
|
|
40
|
<
|
|
165
|
|
|
|
|
|
|
#ifndef PDL_DECLARE_PARAMS_$this->{Name}_$this->{NullDataCheck} |
|
166
|
9
|
|
|
|
|
52
|
#define PDL_DECLARE_PARAMS_$this->{Name}_$this->{NullDataCheck}(@{[join ',', @param_names]}) \\ |
|
167
|
9
|
|
|
|
|
91
|
@{[join " \\\n ", @decls]} |
|
168
|
|
|
|
|
|
|
#endif |
|
169
|
|
|
|
|
|
|
EOF |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
161
|
50
|
|
161
|
|
450
|
sub func_name { $_[1] ? "writebackdata" : "readdata" } |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub broadcastloop_macroname { |
|
175
|
152
|
|
|
152
|
|
196
|
my ($this, $backcode, $which) = @_; |
|
176
|
152
|
|
|
|
|
319
|
"PDL_BROADCASTLOOP_${which}_$this->{Name}_".$this->func_name($backcode); |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub broadcastloop_start { |
|
180
|
9
|
|
|
9
|
|
27
|
my ($this, $funcname) = @_; |
|
181
|
9
|
|
|
|
|
34
|
my ($ord,$pdls) = $this->get_pdls; |
|
182
|
9
|
|
|
|
|
20
|
<
|
|
183
|
|
|
|
|
|
|
PDL_BROADCASTLOOP_START( |
|
184
|
|
|
|
|
|
|
$funcname, |
|
185
|
|
|
|
|
|
|
\$PRIV(broadcast), |
|
186
|
|
|
|
|
|
|
\$PRIV(vtable), |
|
187
|
9
|
|
|
|
|
70
|
@{[ PDL::PP::indent 2, join "", map $pdls->{$ord->[$_]}->do_pointeraccess." += __offsp[$_];\n", 0..$#$ord ]} , |
|
188
|
9
|
|
|
|
|
49
|
(@{[ PDL::PP::indent 2, join "", map ",".$pdls->{$ord->[$_]}->do_pointeraccess." += __tinc1_$ord->[$_] - __tinc0_$ord->[$_] * __tdims0\n", 0..$#$ord ]} ), |
|
189
|
9
|
|
|
|
|
23
|
(@{[ PDL::PP::indent 2, join "", map ",".$pdls->{$ord->[$_]}->do_pointeraccess." += __tinc0_$ord->[$_]\n", 0..$#{$ord} ]} ) |
|
|
9
|
|
|
|
|
31
|
|
|
190
|
|
|
|
|
|
|
) |
|
191
|
|
|
|
|
|
|
EOF |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub broadcastloop_end { |
|
195
|
9
|
|
|
9
|
|
20
|
my ($this) = @_; |
|
196
|
9
|
|
|
|
|
21
|
my ($ord,$pdls) = $this->get_pdls(); |
|
197
|
9
|
|
|
|
|
32
|
<
|
|
198
|
|
|
|
|
|
|
PDL_BROADCASTLOOP_END( |
|
199
|
|
|
|
|
|
|
\$PRIV(broadcast), |
|
200
|
9
|
|
|
|
|
44
|
@{[ PDL::PP::indent 2, join "", map $pdls->{$ord->[$_]}->do_pointeraccess." -= __tinc1_$ord->[$_] * __tdims1 + __offsp[$_];\n", 0..$#$ord ]} |
|
201
|
|
|
|
|
|
|
) |
|
202
|
|
|
|
|
|
|
EOF |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
|
|
205
|
1
|
|
|
1
|
|
5
|
sub sig {$_[0]->{Sig}} |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# This sub determines the index name for this index. |
|
208
|
|
|
|
|
|
|
# For example, a(x,y) and x0 becomes [x,x0] |
|
209
|
3
|
|
|
3
|
|
7
|
sub make_loopind { my($this,$ind) = @_; |
|
210
|
3
|
|
|
|
|
15
|
($ind, my $cntrlval) = split /\s*=\s*/, $ind; |
|
211
|
3
|
|
|
|
|
6
|
my $orig = $ind; |
|
212
|
3
|
|
|
|
|
13
|
while(!$this->{IndObjs}{$ind}) { |
|
213
|
0
|
0
|
|
|
|
0
|
if(!((chop $ind) =~ /[0-9]/)) { |
|
214
|
0
|
|
|
|
|
0
|
confess("Index not found for $_ ($ind)!\n"); |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
} |
|
217
|
3
|
|
50
|
|
|
15
|
my ($initval, $endval, $inc) = split /\s*:\s*/, $cntrlval//''; |
|
218
|
3
|
|
|
|
|
13
|
[$ind,$orig,$initval,$endval,$inc]; |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
my %access2class = ( |
|
222
|
|
|
|
|
|
|
GENERIC => 'PDL::PP::GentypeAccess', |
|
223
|
|
|
|
|
|
|
PPSYM => 'PDL::PP::PpsymAccess', |
|
224
|
|
|
|
|
|
|
); |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub process { |
|
227
|
9
|
|
|
9
|
|
26
|
my ($this, $code, $stack_ref, $broadcastloops_ref, $sizeprivs) = @_; |
|
228
|
9
|
|
|
|
|
29
|
while($code) { |
|
229
|
|
|
|
|
|
|
# Parse next statement |
|
230
|
16
|
50
|
|
|
|
360
|
$code =~ s/^(.*?) # First, some noise is allowed. This may be bad. |
|
231
|
|
|
|
|
|
|
( \$(ISBAD|ISGOOD|SETBAD)\s*\(\s*\$?[a-zA-Z_]\w*\s*\([^)]*\)\s*\) # $ISBAD($a(..)), ditto for ISGOOD and SETBAD |
|
232
|
|
|
|
|
|
|
|\$[a-zA-Z_]\w*\s*\([^)]*\) # $a(...): access |
|
233
|
|
|
|
|
|
|
|\bloop\s*\([^)]+\)\s*%\{ # loop(..) %{ |
|
234
|
|
|
|
|
|
|
|\btypes\s*\([^)]+\)\s*%\{ # types(..) %{ |
|
235
|
|
|
|
|
|
|
|\b(?:thread|broadcast)loop\s*%\{ # broadcastloop %{ |
|
236
|
|
|
|
|
|
|
|%} # %} |
|
237
|
|
|
|
|
|
|
|$)//xs |
|
238
|
|
|
|
|
|
|
or confess("Invalid program $code"); |
|
239
|
16
|
|
|
|
|
47
|
my $control = $2; |
|
240
|
|
|
|
|
|
|
# Store the user code. |
|
241
|
|
|
|
|
|
|
# Some day we shall parse everything. |
|
242
|
16
|
|
|
|
|
39
|
push @{$stack_ref->[-1]},$1; |
|
|
16
|
|
|
|
|
66
|
|
|
243
|
|
|
|
|
|
|
# Then, our control. |
|
244
|
16
|
50
|
|
|
|
38
|
if (!$control) { print("No \$2!\n") if $::PP_VERBOSE; next; } |
|
|
9
|
100
|
|
|
|
26
|
|
|
|
9
|
|
|
|
|
32
|
|
|
245
|
7
|
100
|
|
|
|
61
|
if($control =~ /^loop\s*\(([^)]+)\)\s*%\{/) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
246
|
1
|
|
|
|
|
11
|
my $ob = PDL::PP::Loop->new([split ',',$1], $sizeprivs,$this); |
|
247
|
1
|
50
|
|
|
|
3
|
print "SIZEPRIVSXX: $sizeprivs,",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
|
248
|
1
|
|
|
|
|
2
|
push @{$stack_ref->[-1]},$ob; |
|
|
1
|
|
|
|
|
3
|
|
|
249
|
1
|
|
|
|
|
4
|
push @$stack_ref,$ob; |
|
250
|
|
|
|
|
|
|
} elsif($control =~ /^types\s*\(([^)]+)\)\s*%\{/) { |
|
251
|
0
|
|
|
|
|
0
|
my $ob = PDL::PP::Types->new($1,$this); |
|
252
|
0
|
|
|
|
|
0
|
push @{$stack_ref->[-1]},$ob; |
|
|
0
|
|
|
|
|
0
|
|
|
253
|
0
|
|
|
|
|
0
|
push @$stack_ref,$ob; |
|
254
|
|
|
|
|
|
|
} elsif($control =~ /^(?:thread|broadcast)loop\s*%\{/) { |
|
255
|
1
|
|
|
|
|
10
|
my $ob = PDL::PP::BroadcastLoop->new; |
|
256
|
1
|
|
|
|
|
2
|
push @{$stack_ref->[-1]},$ob; |
|
|
1
|
|
|
|
|
3
|
|
|
257
|
1
|
|
|
|
|
3
|
push @$stack_ref,$ob; |
|
258
|
1
|
|
|
|
|
3
|
$$broadcastloops_ref++; |
|
259
|
|
|
|
|
|
|
} elsif($control =~ /^%}/) { |
|
260
|
2
|
|
|
|
|
6
|
pop @$stack_ref; |
|
261
|
|
|
|
|
|
|
} else { |
|
262
|
3
|
|
|
|
|
16
|
my ($rest, @add) = $this->expand($control.$code); |
|
263
|
3
|
|
|
|
|
7
|
push @{$stack_ref->[-1]}, @add; |
|
|
3
|
|
|
|
|
7
|
|
|
264
|
3
|
|
|
|
|
11
|
$code = $rest; |
|
265
|
|
|
|
|
|
|
} |
|
266
|
|
|
|
|
|
|
} # while: $code |
|
267
|
|
|
|
|
|
|
} |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
# my ( $broadcastloops, $coderef, $sizeprivs ) = $this->separate_code( $code ); |
|
270
|
|
|
|
|
|
|
# |
|
271
|
|
|
|
|
|
|
# separates the code into an array of C fragments (strings), |
|
272
|
|
|
|
|
|
|
# variable references (strings starting with $) and |
|
273
|
|
|
|
|
|
|
# loops (array references, 1. item = variable. |
|
274
|
|
|
|
|
|
|
# |
|
275
|
|
|
|
|
|
|
sub separate_code { |
|
276
|
10
|
|
|
10
|
|
26
|
my ( $this, $code ) = @_; |
|
277
|
|
|
|
|
|
|
# First check for standard code errors: |
|
278
|
10
|
|
|
|
|
48
|
$this->catch_code_errors($code); |
|
279
|
9
|
|
|
|
|
60
|
my @stack = my $coderef = PDL::PP::Block->new; |
|
280
|
9
|
|
|
|
|
22
|
my $broadcastloops = 0; |
|
281
|
9
|
|
|
|
|
15
|
my $sizeprivs = {}; |
|
282
|
9
|
|
|
|
|
41
|
$this->process($code, \@stack, \$broadcastloops, $sizeprivs); |
|
283
|
9
|
|
|
|
|
34
|
( $broadcastloops, $coderef, $sizeprivs ); |
|
284
|
|
|
|
|
|
|
} # sub: separate_code() |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
my $macro_pat = qr/\w+/; |
|
287
|
|
|
|
|
|
|
sub expand { |
|
288
|
3
|
|
|
3
|
|
9
|
my ($this, $text) = @_; |
|
289
|
3
|
|
|
|
|
9
|
my (undef, $pdl, $inds, $rest) = PDL::PP::Rule::Substitute::macro_extract($text, $macro_pat); |
|
290
|
3
|
|
|
|
|
8
|
my @add; |
|
291
|
3
|
100
|
|
|
|
25
|
if($pdl =~ /^T/) {@add = PDL::PP::MacroAccess->new($pdl,$inds, |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
292
|
1
|
|
|
|
|
17
|
$this->{Generictypes},$this->{Name});} |
|
293
|
0
|
|
|
|
|
0
|
elsif(my $c = $access2class{$pdl}) {@add = $c->new($pdl,$inds)} |
|
294
|
|
|
|
|
|
|
elsif($pdl =~ /^(P|)(ISBAD|ISGOOD|SETBAD)(VAR|)$/) { |
|
295
|
0
|
|
|
|
|
0
|
my ($opcode, $name) = ($2); |
|
296
|
0
|
|
0
|
|
|
0
|
my $get = $1 || $3; |
|
297
|
0
|
0
|
|
|
|
0
|
if (!$get) { |
|
|
|
0
|
|
|
|
|
|
|
298
|
0
|
|
|
|
|
0
|
$inds =~ s/^\$?([a-zA-Z_]\w*)\s*//; # $ is optional |
|
299
|
0
|
|
|
|
|
0
|
$name = $1; |
|
300
|
0
|
|
|
|
|
0
|
$inds = substr $inds, 1, -1; # chop off brackets |
|
301
|
|
|
|
|
|
|
} elsif ($get eq 'P') { |
|
302
|
0
|
|
|
|
|
0
|
($name, $inds) = PDL::PP::Rule::Substitute::split_cpp($inds); |
|
303
|
|
|
|
|
|
|
} else { |
|
304
|
0
|
|
|
|
|
0
|
($inds, $name) = PDL::PP::Rule::Substitute::split_cpp($inds); |
|
305
|
|
|
|
|
|
|
} |
|
306
|
0
|
|
|
|
|
0
|
@add = PDL::PP::BadAccess->new($opcode,$get,$name,$inds,$this); |
|
307
|
|
|
|
|
|
|
} |
|
308
|
2
|
|
|
|
|
18
|
elsif($this->{ParObjs}{$pdl}) {@add = PDL::PP::Access->new($pdl,$inds)} |
|
309
|
|
|
|
|
|
|
else { |
|
310
|
0
|
|
|
|
|
0
|
confess "unknown construct $pdl($inds)"; |
|
311
|
|
|
|
|
|
|
} |
|
312
|
3
|
|
|
|
|
12
|
($rest, @add); |
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# This is essentially a collection of regexes that look for standard code |
|
316
|
|
|
|
|
|
|
# errors and croaks with an explanation if they are found. |
|
317
|
|
|
|
|
|
|
sub catch_code_errors { |
|
318
|
10
|
|
|
10
|
|
25
|
my ($this, $code_string) = @_; |
|
319
|
10
|
|
|
|
|
75
|
my $prefix = "pp_def($this->{Name}): "; |
|
320
|
10
|
100
|
|
|
|
135
|
report_error("${prefix}Expected dimension name after 'loop' and before '%{'", $1) |
|
321
|
|
|
|
|
|
|
if $code_string =~ /(.*\bloop\s*%\{)/s; |
|
322
|
|
|
|
|
|
|
} |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# Report an error as precisely as possible. If they have #line directives |
|
325
|
|
|
|
|
|
|
# in the code string, use that in the reporting; otherwise, use standard |
|
326
|
|
|
|
|
|
|
# Carp mechanisms |
|
327
|
|
|
|
|
|
|
my $line_re = qr/(?:PDL_LINENO_START|#\s*line)\s+(\d+)\s+"([^"]*)"/; |
|
328
|
|
|
|
|
|
|
sub report_error { |
|
329
|
1
|
|
|
1
|
|
6
|
my ($message, $code) = @_; |
|
330
|
|
|
|
|
|
|
# Just croak if they didn't supply a #line directive: |
|
331
|
1
|
50
|
|
|
|
358
|
croak($message) if $code !~ $line_re; |
|
332
|
|
|
|
|
|
|
# Find the line at which the error occurred: |
|
333
|
0
|
|
|
|
|
0
|
my $line = 0; |
|
334
|
0
|
|
|
|
|
0
|
my $filename; |
|
335
|
0
|
|
|
|
|
0
|
LINE: foreach (split /\n/, $code) { |
|
336
|
0
|
|
|
|
|
0
|
$line++; |
|
337
|
0
|
0
|
|
|
|
0
|
if (/$line_re/) { |
|
338
|
0
|
|
|
|
|
0
|
$line = $1; |
|
339
|
0
|
|
|
|
|
0
|
$filename = $2; |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
} |
|
342
|
0
|
|
|
|
|
0
|
die "$message at $filename line $line\n"; |
|
343
|
|
|
|
|
|
|
} |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
##################################################################### |
|
346
|
|
|
|
|
|
|
# |
|
347
|
|
|
|
|
|
|
# Encapsulate the parsing code objects |
|
348
|
|
|
|
|
|
|
# |
|
349
|
|
|
|
|
|
|
# All objects have two methods: |
|
350
|
|
|
|
|
|
|
# new - constructor |
|
351
|
|
|
|
|
|
|
# get_str - get the string to be put into the xsub. |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
354
|
|
|
|
|
|
|
PDL::PP::Block; |
|
355
|
|
|
|
|
|
|
|
|
356
|
9
|
|
|
9
|
|
27
|
sub new { my($type) = @_; bless [],$type; } |
|
|
9
|
|
|
|
|
26
|
|
|
357
|
|
|
|
|
|
|
|
|
358
|
68
|
|
|
68
|
|
271
|
sub myoffs { 0 } |
|
359
|
138
|
|
|
138
|
|
293
|
sub myextraindent { 0 } |
|
360
|
|
|
|
68
|
|
|
sub myprelude {} |
|
361
|
|
|
|
66
|
|
|
sub mypostlude {} |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub get_str { |
|
364
|
147
|
|
|
147
|
|
267
|
my ($this,$parent,$context) = @_; |
|
365
|
147
|
|
|
|
|
309
|
my $str = $this->myprelude($parent,$context); |
|
366
|
147
|
|
50
|
|
|
318
|
$str .= PDL::PP::indent 2, $this->get_str_int($parent,$context)//''; |
|
367
|
141
|
|
100
|
|
|
255
|
$str .= $this->mypostlude($parent,$context)//''; |
|
368
|
141
|
|
|
|
|
453
|
return $str; |
|
369
|
|
|
|
|
|
|
} |
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
sub get_str_int { |
|
372
|
147
|
|
|
147
|
|
198
|
my ( $this, $parent, $context ) = @_; |
|
373
|
147
|
|
|
|
|
145
|
my $nth=0; |
|
374
|
147
|
|
|
|
|
151
|
my $str = ""; |
|
375
|
147
|
|
|
|
|
152
|
MYLOOP: while(1) { |
|
376
|
347
|
|
100
|
|
|
768
|
my $it = $this->can('myitemstart') && $this->myitemstart($parent,$nth); |
|
377
|
347
|
100
|
100
|
|
|
701
|
last MYLOOP if $nth and !$it; |
|
378
|
206
|
|
100
|
|
|
450
|
$str .= $it//''; |
|
379
|
206
|
|
|
|
|
301
|
$str .= PDL::PP::indent $this->myextraindent, join '', $this->get_contained($parent,$context); |
|
380
|
200
|
100
|
66
|
|
|
589
|
$str .= $it if $it = $this->can('myitemend') && $this->myitemend($parent,$nth); |
|
381
|
200
|
|
|
|
|
210
|
$nth++; |
|
382
|
|
|
|
|
|
|
} |
|
383
|
141
|
|
|
|
|
364
|
return $str; |
|
384
|
|
|
|
|
|
|
} # get_str_int() |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub get_contained { |
|
387
|
206
|
|
|
206
|
|
248
|
my ($this, $parent, $context) = @_; |
|
388
|
206
|
100
|
|
|
|
294
|
map ref($_) ? $_->get_str($parent, $context) : $_, |
|
389
|
|
|
|
|
|
|
@$this[$this->myoffs..$#$this]; |
|
390
|
|
|
|
|
|
|
} |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
sub enter { |
|
393
|
17
|
|
|
17
|
|
32
|
my ($this, $new) = @_; |
|
394
|
17
|
|
|
|
|
63
|
push @$new, $this; |
|
395
|
17
|
|
|
|
|
28
|
$new; |
|
396
|
|
|
|
|
|
|
} |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
########################### |
|
399
|
|
|
|
|
|
|
# |
|
400
|
|
|
|
|
|
|
# Deal with bad code |
|
401
|
|
|
|
|
|
|
# - ie create something like |
|
402
|
|
|
|
|
|
|
# if ( badflag ) { badcode } else { goodcode } |
|
403
|
|
|
|
|
|
|
# |
|
404
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
405
|
|
|
|
|
|
|
PDL::PP::BadSwitch; |
|
406
|
|
|
|
|
|
|
our @ISA = "PDL::PP::Block"; |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub new { |
|
409
|
9
|
|
|
9
|
|
22
|
my($type,$good,$bad) = @_; |
|
410
|
9
|
|
|
|
|
21
|
return bless [$good,$bad], $type; |
|
411
|
|
|
|
|
|
|
} |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
sub get_str { |
|
414
|
9
|
|
|
9
|
|
26
|
my ($this,$parent,$context) = @_; |
|
415
|
9
|
|
|
|
|
25
|
my $good = $this->[0]; |
|
416
|
9
|
|
|
|
|
15
|
my $good_str = <
|
|
417
|
|
|
|
|
|
|
#define PDL_IF_BAD(t,f) f |
|
418
|
9
|
|
|
|
|
59
|
@{[ $good->get_str($parent,$context) |
|
419
|
|
|
|
|
|
|
]}#undef PDL_IF_BAD |
|
420
|
|
|
|
|
|
|
EOF |
|
421
|
7
|
50
|
|
|
|
69
|
return $good_str if !defined(my $bad = $this->[1]); |
|
422
|
0
|
|
|
|
|
0
|
my $str = <
|
|
423
|
|
|
|
|
|
|
if ( \$PRIV(bvalflag) ) { /* ** do 'bad' Code ** */ |
|
424
|
|
|
|
|
|
|
#define PDL_BAD_CODE |
|
425
|
|
|
|
|
|
|
#define PDL_IF_BAD(t,f) t |
|
426
|
0
|
|
|
|
|
0
|
@{[ PDL::PP::indent 2, $bad->get_str($parent,$context) |
|
427
|
|
|
|
|
|
|
]} #undef PDL_BAD_CODE |
|
428
|
|
|
|
|
|
|
#undef PDL_IF_BAD |
|
429
|
|
|
|
|
|
|
} else { /* ** else do 'good' Code ** */ |
|
430
|
0
|
|
|
|
|
0
|
@{[ PDL::PP::indent 2, $good_str |
|
431
|
|
|
|
|
|
|
]}} |
|
432
|
|
|
|
|
|
|
EOF |
|
433
|
|
|
|
|
|
|
} |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
436
|
|
|
|
|
|
|
PDL::PP::Loop; |
|
437
|
|
|
|
|
|
|
our @ISA = "PDL::PP::Block"; |
|
438
|
|
|
|
|
|
|
|
|
439
|
1
|
|
|
1
|
|
4
|
sub new { my($type,$args,$sizeprivs,$parent) = @_; |
|
440
|
1
|
|
|
|
|
3
|
my $this = bless [$args],$type; |
|
441
|
1
|
|
|
|
|
4
|
for (@$args) { |
|
442
|
1
|
50
|
|
|
|
3
|
print "SIZP $sizeprivs, $_\n" if $::PP_VERBOSE; |
|
443
|
1
|
|
|
|
|
5
|
my $i = $parent->make_loopind($_); |
|
444
|
1
|
|
|
|
|
4
|
my $i_size = $parent->sig->dims_obj->ind_obj($i->[0])->get_size; |
|
445
|
1
|
|
|
|
|
5
|
$sizeprivs->{$i->[0]} = "register PDL_Indx __$i->[0]_size = $i_size;\n"; |
|
446
|
1
|
50
|
|
|
|
6
|
print "SP :",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
|
447
|
|
|
|
|
|
|
} |
|
448
|
1
|
|
|
|
|
3
|
return $this; |
|
449
|
|
|
|
|
|
|
} |
|
450
|
|
|
|
|
|
|
|
|
451
|
2
|
|
|
2
|
|
24
|
sub myoffs { return 1; } |
|
452
|
2
|
|
|
2
|
|
4
|
sub myprelude { my($this,$parent,$context) = @_; |
|
453
|
2
|
|
|
|
|
15
|
my $text = ""; |
|
454
|
|
|
|
|
|
|
push @$context, map { |
|
455
|
2
|
|
|
|
|
6
|
my $i = $parent->make_loopind($_); |
|
456
|
2
|
|
|
|
|
7
|
my ($loopdim, $loopvar, $loopstart, $loopend, $loopinc) = @$i; |
|
457
|
2
|
|
|
|
|
3
|
my $loopstopvar = "__${loopvar}_stop"; |
|
458
|
2
|
|
50
|
|
|
12
|
$loopinc ||= 1; my $cmp; |
|
|
2
|
|
|
|
|
3
|
|
|
459
|
2
|
50
|
|
|
|
8
|
if ($loopinc =~ /^-/) { |
|
460
|
0
|
0
|
0
|
|
|
0
|
$loopstart = !(defined $loopstart && length $loopstart) ? "(__${loopdim}_size-1)" : |
|
|
|
0
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
$loopstart =~ /^-/ ? "PDLMIN((__${loopdim}_size$loopstart), (__${loopdim}_size-1))" : |
|
462
|
|
|
|
|
|
|
"PDLMIN($loopstart, (__${loopdim}_size-1))"; |
|
463
|
0
|
|
|
|
|
0
|
$cmp = ">="; |
|
464
|
0
|
0
|
|
|
|
0
|
$loopend = !$loopend ? 0 : |
|
|
|
0
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
$loopend =~ /^-/ ? "PDLMAX((__${loopdim}_size$loopend),0)" : |
|
466
|
|
|
|
|
|
|
"PDLMAX(($loopend),0)"; |
|
467
|
|
|
|
|
|
|
} else { |
|
468
|
|
|
|
|
|
|
# count upwards |
|
469
|
2
|
0
|
|
|
|
6
|
$loopstart = !$loopstart ? 0 : |
|
|
|
50
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
$loopstart =~ /^-/ ? "PDLMAX((__${loopdim}_size$loopstart),0)" : |
|
471
|
|
|
|
|
|
|
"PDLMAX(($loopstart),0)"; |
|
472
|
2
|
|
|
|
|
5
|
$cmp = "<"; |
|
473
|
2
|
0
|
33
|
|
|
8
|
$loopend = !(defined $loopend && length $loopend) ? "(__${loopdim}_size)" : |
|
|
|
50
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
$loopend =~ /^-/ ? "(__${loopdim}_size$loopend)" : |
|
475
|
|
|
|
|
|
|
"PDLMIN($loopend, (__${loopdim}_size))"; |
|
476
|
|
|
|
|
|
|
} |
|
477
|
2
|
|
|
|
|
25
|
$text .= "{/* Open $_ */ PDL_EXPAND2(register PDL_Indx $loopvar=$loopstart, $loopstopvar=$loopend); for(; $loopvar$cmp$loopstopvar; $loopvar+=$loopinc) {"; |
|
478
|
2
|
|
|
|
|
8
|
$i; |
|
479
|
2
|
|
|
|
|
4
|
} @{$this->[0]}; |
|
|
2
|
|
|
|
|
6
|
|
|
480
|
2
|
|
|
|
|
5
|
$text; |
|
481
|
|
|
|
|
|
|
} |
|
482
|
2
|
|
|
2
|
|
5
|
sub mypostlude { my($this,$parent,$context) = @_; |
|
483
|
2
|
|
|
|
|
5
|
splice @$context, - ($#{$this->[0]}+1); |
|
|
2
|
|
|
|
|
8
|
|
|
484
|
2
|
|
|
|
|
5
|
return join '', map "}} /* Close $_ */", @{$this->[0]}; |
|
|
2
|
|
|
|
|
27
|
|
|
485
|
|
|
|
|
|
|
} |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
488
|
|
|
|
|
|
|
PDL::PP::GenericSwitch; |
|
489
|
3
|
|
|
3
|
|
38
|
use Carp; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
442
|
|
|
490
|
|
|
|
|
|
|
our @ISA = "PDL::PP::Block"; |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
# make the typetable from info in PDL::Types |
|
493
|
3
|
|
|
3
|
|
24
|
use PDL::Types ':All'; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
5322
|
|
|
494
|
|
|
|
|
|
|
my %type2canonical = map +($_->ppsym=>$_,$_->identifier=>$_), types(); |
|
495
|
|
|
|
|
|
|
my @typetable = map [$_->ppsym, $_], types(); |
|
496
|
9
|
|
|
9
|
|
20
|
sub get_generictyperecs { my($types) = @_; |
|
497
|
9
|
|
|
|
|
76
|
my @bad = grep !$type2canonical{$_}, @$types; |
|
498
|
9
|
50
|
|
|
|
24
|
confess "Invalid GenericType (@bad)!" if @bad; |
|
499
|
9
|
|
|
|
|
16
|
my %wanted; @wanted{map $type2canonical{$_}->ppsym, @$types} = (); |
|
|
9
|
|
|
|
|
110
|
|
|
500
|
9
|
|
|
|
|
204
|
[ map $_->[1], grep exists $wanted{$_->[0]}, @typetable ]; |
|
501
|
|
|
|
|
|
|
} |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
# Types: BSULFD |
|
504
|
|
|
|
|
|
|
sub new { |
|
505
|
9
|
|
|
9
|
|
29
|
my ($type,$types,$name,$varnames,$whattype,$if_gentype) = @_; |
|
506
|
9
|
|
|
|
|
14
|
my %vars; @vars{@$varnames} = (); |
|
|
9
|
|
|
|
|
27
|
|
|
507
|
9
|
|
|
|
|
30
|
bless [get_generictyperecs($types), $name, \%vars, $whattype, $if_gentype], $type; |
|
508
|
|
|
|
|
|
|
} |
|
509
|
|
|
|
|
|
|
|
|
510
|
68
|
|
|
68
|
|
249
|
sub myoffs {5} |
|
511
|
68
|
|
|
68
|
|
132
|
sub myextraindent { 2 } |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
sub myprelude { |
|
514
|
9
|
|
|
9
|
|
18
|
my ($this,$parent,$context) = @_; |
|
515
|
9
|
|
|
|
|
11
|
push @{$parent->{Gencurtype}}, undef; # so that $GENERIC can get at it |
|
|
9
|
|
|
|
|
25
|
|
|
516
|
|
|
|
|
|
|
die "ERROR: need to rethink NaN support in GenericSwitch\n" |
|
517
|
9
|
0
|
33
|
|
|
26
|
if defined $this->[1] and $parent->{ftypes_type}; |
|
518
|
9
|
|
|
|
|
27
|
qq[switch ($this->[3]) { /* Start generic switch */\n]; |
|
519
|
|
|
|
|
|
|
} |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
my @GENTYPE_ATTRS = qw(integer real unsigned); |
|
522
|
|
|
|
|
|
|
sub myitemstart { |
|
523
|
75
|
|
|
75
|
|
104
|
my ($this,$parent,$nth) = @_; |
|
524
|
75
|
|
100
|
|
|
152
|
my $item = $this->[0][$nth] || return ""; |
|
525
|
68
|
|
|
|
|
102
|
$parent->{Gencurtype}[-1] = $item; |
|
526
|
68
|
50
|
|
|
|
110
|
@$parent{qw(ftypes_type ftypes_vars)} = ($item, $this->[2]) if defined $this->[1]; |
|
527
|
68
|
|
|
|
|
103
|
my ($ord,$pdls) = $parent->get_pdls; |
|
528
|
68
|
|
|
|
|
210
|
my %istyped = map +($_=>1), grep $pdls->{$_}{FlagTypeOverride}, @$ord; |
|
529
|
|
|
|
|
|
|
my @param_ctypes = ($item->ctype, $item->ppsym, |
|
530
|
|
|
|
|
|
|
map +($pdls->{$_}->adjusted_type($item)->ctype, |
|
531
|
|
|
|
|
|
|
$pdls->{$_}->adjusted_type($item)->ppsym), |
|
532
|
68
|
|
|
|
|
118
|
grep $istyped{$_}, @$ord); |
|
533
|
68
|
|
|
|
|
188
|
my $decls = keys %{$this->[2]} == @$ord |
|
534
|
68
|
|
|
|
|
598
|
? "PDL_DECLARE_PARAMS_$parent->{Name}_$parent->{NullDataCheck}(@{[join ',', @param_ctypes]})\n" |
|
535
|
|
|
|
|
|
|
: join '', map $_->get_xsdatapdecl($_->adjusted_type($item)->ctype, $parent->{NullDataCheck}, $_->adjusted_type($item)->ppsym, $parent->{BadFlag}), |
|
536
|
68
|
50
|
|
|
|
89
|
map $parent->{ParObjs}{$_}, sort keys %{$this->[2]}; |
|
|
0
|
|
|
|
|
0
|
|
|
537
|
68
|
0
|
|
|
|
151
|
my @gentype_decls = !$this->[4] ? () : map "#define PDL_IF_GENTYPE_".uc($_)."(t,f) ". |
|
|
|
50
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
($item->$_ ? 't' : 'f')."\n", |
|
539
|
|
|
|
|
|
|
@GENTYPE_ATTRS; |
|
540
|
68
|
|
|
|
|
75
|
"case @{[$item->sym]}: {\n" . |
|
|
68
|
|
|
|
|
128
|
|
|
541
|
|
|
|
|
|
|
PDL::PP::indent 2, join '', |
|
542
|
|
|
|
|
|
|
@gentype_decls, |
|
543
|
|
|
|
|
|
|
$decls; |
|
544
|
|
|
|
|
|
|
} |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
sub myitemend { |
|
547
|
66
|
|
|
66
|
|
91
|
my ($this,$parent,$nth) = @_; |
|
548
|
66
|
|
50
|
|
|
150
|
my $item = $this->[0][$nth] || return ""; |
|
549
|
66
|
50
|
|
|
|
289
|
join '', |
|
550
|
|
|
|
|
|
|
"\n", |
|
551
|
|
|
|
|
|
|
(!$this->[4] ? () : map "#undef PDL_IF_GENTYPE_".uc($_)."\n", @GENTYPE_ATTRS), |
|
552
|
|
|
|
|
|
|
"} break;\n"; |
|
553
|
|
|
|
|
|
|
} |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
sub mypostlude { |
|
556
|
7
|
|
|
7
|
|
18
|
my($this,$parent,$context) = @_; |
|
557
|
7
|
|
|
|
|
24
|
pop @{$parent->{Gencurtype}}; # and clean up the Gentype stack |
|
|
7
|
|
|
|
|
21
|
|
|
558
|
7
|
50
|
|
|
|
24
|
$parent->{ftypes_type} = undef if defined $this->[1]; |
|
559
|
7
|
|
|
|
|
12
|
my $supported = join '', map $_->ppsym, @{$this->[0]}; |
|
|
7
|
|
|
|
|
26
|
|
|
560
|
7
|
|
|
|
|
40
|
" default: return PDL->make_error(PDL_EUSERERROR, \"PP INTERNAL ERROR in $parent->{Name}: unhandled datatype(%d), only handles ($supported)! PLEASE MAKE A BUG REPORT\\n\", $this->[3]);\n}\n"; |
|
561
|
|
|
|
|
|
|
} |
|
562
|
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
#### |
|
564
|
|
|
|
|
|
|
# |
|
565
|
|
|
|
|
|
|
# This relies on PP.pm making sure that initbroadcaststruct always sets |
|
566
|
|
|
|
|
|
|
# up the two first dimensions even when they are not necessary. |
|
567
|
|
|
|
|
|
|
# |
|
568
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
569
|
|
|
|
|
|
|
PDL::PP::BroadcastLoop; |
|
570
|
3
|
|
|
3
|
|
29
|
use Carp; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
810
|
|
|
571
|
|
|
|
|
|
|
our @ISA = "PDL::PP::Block"; |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
sub new { |
|
574
|
9
|
|
|
9
|
|
17
|
my $type = shift; |
|
575
|
9
|
|
|
|
|
40
|
bless [],$type; |
|
576
|
|
|
|
|
|
|
} |
|
577
|
68
|
|
|
68
|
|
159
|
sub myoffs { return 0; } |
|
578
|
|
|
|
|
|
|
sub myprelude { |
|
579
|
68
|
|
|
68
|
|
100
|
my($this,$parent,$context,$backcode) = @_; |
|
580
|
68
|
|
|
|
|
110
|
$parent->broadcastloop_macroname($backcode, 'START'); |
|
581
|
|
|
|
|
|
|
} |
|
582
|
|
|
|
|
|
|
|
|
583
|
66
|
|
|
66
|
|
95
|
sub mypostlude {my($this,$parent,$context,$backcode) = @_; |
|
584
|
66
|
|
|
|
|
108
|
$parent->broadcastloop_macroname($backcode, 'END'); |
|
585
|
|
|
|
|
|
|
} |
|
586
|
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
# Simple subclass of BroadcastLoop to implement writeback code |
|
588
|
|
|
|
|
|
|
# |
|
589
|
|
|
|
|
|
|
# |
|
590
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
591
|
|
|
|
|
|
|
PDL::PP::BackCodeBroadcastLoop; |
|
592
|
3
|
|
|
3
|
|
34
|
use Carp; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
737
|
|
|
593
|
|
|
|
|
|
|
our @ISA = "PDL::PP::BroadcastLoop"; |
|
594
|
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
sub myprelude { |
|
596
|
0
|
|
|
0
|
|
0
|
my($this,$parent,$context,$backcode) = @_; |
|
597
|
|
|
|
|
|
|
# Set backcode flag if not defined. This will make the parent |
|
598
|
|
|
|
|
|
|
# myprelude emit proper writeback code |
|
599
|
0
|
|
0
|
|
|
0
|
$this->SUPER::myprelude($parent, $context, $backcode // 1); |
|
600
|
|
|
|
|
|
|
} |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
sub mypostlude { |
|
603
|
0
|
|
|
0
|
|
0
|
my($this,$parent,$context,$backcode) = @_; |
|
604
|
|
|
|
|
|
|
# Set backcode flag if not defined. This will make the parent |
|
605
|
|
|
|
|
|
|
# mypostlude emit proper writeback code |
|
606
|
0
|
|
0
|
|
|
0
|
$this->SUPER::mypostlude($parent, $context, $backcode // 1); |
|
607
|
|
|
|
|
|
|
} |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
########################### |
|
610
|
|
|
|
|
|
|
# |
|
611
|
|
|
|
|
|
|
# Encapsulate a types() switch |
|
612
|
|
|
|
|
|
|
# |
|
613
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
614
|
|
|
|
|
|
|
PDL::PP::Types; |
|
615
|
3
|
|
|
3
|
|
27
|
use Carp; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
276
|
|
|
616
|
3
|
|
|
3
|
|
34
|
use PDL::Types ':All'; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
2017
|
|
|
617
|
|
|
|
|
|
|
our @ISA = "PDL::PP::Block"; |
|
618
|
|
|
|
|
|
|
my %types = map +($_=>1), ppdefs_all; # BSUL.... |
|
619
|
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
sub new { |
|
621
|
0
|
|
|
0
|
|
0
|
my($type,$ts,$parent) = @_; |
|
622
|
0
|
|
|
|
|
0
|
my @bad = grep !$types{$_}, my @ts = split '', $ts; |
|
623
|
0
|
0
|
|
|
|
0
|
confess "Invalid type access (@bad) in '$ts'!" if @bad; |
|
624
|
0
|
|
|
|
|
0
|
bless [+{map +($_=>1), @ts}],$type; } |
|
625
|
0
|
|
|
0
|
|
0
|
sub myoffs { return 1; } |
|
626
|
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
sub get_str { |
|
628
|
0
|
|
|
0
|
|
0
|
my ($this,$parent,$context) = @_; |
|
629
|
|
|
|
|
|
|
confess "types() outside a generic switch" |
|
630
|
0
|
0
|
|
|
|
0
|
unless defined(my $type = $parent->{Gencurtype}[-1]); |
|
631
|
0
|
0
|
|
|
|
0
|
return '' if !$this->[0]{$type->ppsym}; |
|
632
|
0
|
|
|
|
|
0
|
join '', $this->get_contained($parent,$context); |
|
633
|
|
|
|
|
|
|
} |
|
634
|
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
637
|
|
|
|
|
|
|
PDL::PP::Access; |
|
638
|
3
|
|
|
3
|
|
31
|
use Carp; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
870
|
|
|
639
|
|
|
|
|
|
|
|
|
640
|
2
|
|
|
2
|
|
7
|
sub new { my($type,$pdl,$inds) = @_; |
|
641
|
2
|
|
|
|
|
8
|
bless [$pdl,$inds],$type; |
|
642
|
|
|
|
|
|
|
} |
|
643
|
|
|
|
|
|
|
|
|
644
|
2
|
|
|
2
|
|
7
|
sub get_str { my($this,$parent,$context) = @_; |
|
645
|
|
|
|
|
|
|
$parent->{ParObjs}{$this->[0]}->do_access($this->[1],$context) |
|
646
|
2
|
50
|
|
|
|
28
|
if defined($parent->{ParObjs}{$this->[0]}); |
|
647
|
|
|
|
|
|
|
} |
|
648
|
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
########################### |
|
650
|
|
|
|
|
|
|
# Encapsulate a check on whether a value is good or bad |
|
651
|
|
|
|
|
|
|
# handles both checking (good/bad) and setting (bad) |
|
652
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
653
|
|
|
|
|
|
|
PDL::PP::BadAccess; |
|
654
|
3
|
|
|
3
|
|
99
|
use Carp; |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
2761
|
|
|
655
|
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
sub new { |
|
657
|
0
|
|
|
0
|
|
0
|
my ( $type, $opcode, $get, $name, $inds, $parent ) = @_; |
|
658
|
|
|
|
|
|
|
die "\nIt looks like you have tried a $get \$${opcode}() macro on an" . |
|
659
|
|
|
|
|
|
|
" unknown ndarray <$name($inds)>\n" |
|
660
|
0
|
0
|
|
|
|
0
|
unless defined($parent->{ParObjs}{$name}); |
|
661
|
0
|
|
|
|
|
0
|
bless [$opcode, $get, $name, $inds], $type; |
|
662
|
|
|
|
|
|
|
} |
|
663
|
|
|
|
|
|
|
|
|
664
|
0
|
|
|
0
|
|
0
|
sub _isbad { "PDL_ISBAD2($_[0],$_[1],$_[2],$_[3])" } |
|
665
|
|
|
|
|
|
|
our %ops = ( |
|
666
|
|
|
|
|
|
|
ISBAD => \&_isbad, |
|
667
|
|
|
|
|
|
|
ISGOOD => sub {'!'.&_isbad}, |
|
668
|
|
|
|
|
|
|
SETBAD => sub{join '=', @_[0,1]}, |
|
669
|
|
|
|
|
|
|
); |
|
670
|
|
|
|
|
|
|
my %getters = ( |
|
671
|
|
|
|
|
|
|
'' => sub {my ($obj, $inds, $context)=@_; $obj->do_access($inds,$context)}, |
|
672
|
|
|
|
|
|
|
P => sub {my ($obj, $inds)=@_; $obj->do_pointeraccess.$inds}, |
|
673
|
|
|
|
|
|
|
VAR => sub {my ($obj, $inds)=@_; $inds}, |
|
674
|
|
|
|
|
|
|
); |
|
675
|
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
sub get_str { |
|
677
|
0
|
|
|
0
|
|
0
|
my ($this,$parent,$context) = @_; |
|
678
|
0
|
|
|
|
|
0
|
my ($opcode, $get, $name, $inds) = @$this; |
|
679
|
|
|
|
|
|
|
confess "generic type access outside a generic switch in $name" |
|
680
|
0
|
0
|
|
|
|
0
|
unless defined $parent->{Gencurtype}[-1]; |
|
681
|
0
|
0
|
|
|
|
0
|
print "PDL::PP::BadAccess sent [$opcode] [$name] [$inds]\n" if $::PP_VERBOSE; |
|
682
|
|
|
|
|
|
|
die "ERROR: unknown check <$opcode> sent to PDL::PP::BadAccess\n" |
|
683
|
0
|
0
|
|
|
|
0
|
unless defined( my $op = $ops{$opcode} ); |
|
684
|
|
|
|
|
|
|
die "ERROR: something screwy in PDL::PP::BadAccess (PP/PDLCode.pm)\n" |
|
685
|
0
|
0
|
|
|
|
0
|
unless defined( my $obj = $parent->{ParObjs}{$name} ); |
|
686
|
0
|
|
|
|
|
0
|
my $lhs = $getters{$get}->($obj, $inds, $context); |
|
687
|
0
|
|
|
|
|
0
|
my $rhs = "${name}_badval"; |
|
688
|
0
|
0
|
|
|
|
0
|
print "DBG: [$lhs $op $rhs]\n" if $::PP_VERBOSE; |
|
689
|
|
|
|
|
|
|
my $type = exists $parent->{ftypes_vars}{$name} |
|
690
|
|
|
|
|
|
|
? $parent->{ftypes_type} |
|
691
|
0
|
0
|
|
|
|
0
|
: $obj->adjusted_type($parent->{Gencurtype}[-1]); |
|
692
|
0
|
|
|
|
|
0
|
$op->($lhs, $rhs, $type->ppsym, $rhs."_isnan"); |
|
693
|
|
|
|
|
|
|
} |
|
694
|
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
697
|
|
|
|
|
|
|
PDL::PP::MacroAccess; |
|
698
|
3
|
|
|
3
|
|
45
|
use Carp; |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
219
|
|
|
699
|
3
|
|
|
3
|
|
16
|
use PDL::Types ':All'; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
2857
|
|
|
700
|
|
|
|
|
|
|
my $types = join '',ppdefs_all; |
|
701
|
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
sub new { |
|
703
|
1
|
|
|
1
|
|
5
|
my ($type, $pdl, $inds, $gentypes, $name) = @_; |
|
704
|
1
|
|
|
|
|
13
|
my @normalised = map PDL::Type->new($_)->ppsym, @$gentypes; |
|
705
|
1
|
50
|
|
|
|
11
|
$pdl =~ /^\s*T([A-Z]+)\s*$/ |
|
706
|
|
|
|
|
|
|
or confess("Macroaccess wrong in $name (allowed types $types): was '$pdl'\n"); |
|
707
|
1
|
|
|
|
|
8
|
my @ilst = split '', $1; |
|
708
|
1
|
|
|
|
|
8
|
my @lst = PDL::PP::Rule::Substitute::split_cpp($inds); |
|
709
|
1
|
50
|
|
|
|
5
|
confess "Macroaccess: different nos of args $pdl (@{[scalar @lst]}=@lst) vs (@{[scalar @ilst]}=@ilst)\n" if @lst != @ilst; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
710
|
1
|
|
|
|
|
3
|
my %type2value; @type2value{@ilst} = @lst; |
|
|
1
|
|
|
|
|
8
|
|
|
711
|
|
|
|
|
|
|
confess "$name has no Macro for generic type $_ (has $pdl)\n" |
|
712
|
1
|
|
|
|
|
7
|
for grep !exists $type2value{$_}, @normalised; |
|
713
|
1
|
|
|
|
|
3
|
my %gts; @gts{@normalised} = (); |
|
|
1
|
|
|
|
|
5
|
|
|
714
|
|
|
|
|
|
|
warn "Macro for unsupported generic type identifier $_\n" |
|
715
|
1
|
|
|
|
|
6
|
for grep !exists $gts{$_}, @ilst; |
|
716
|
1
|
|
|
|
|
8
|
bless [\%type2value, $name], $type; |
|
717
|
|
|
|
|
|
|
} |
|
718
|
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
sub get_str { |
|
720
|
4
|
|
|
4
|
|
8
|
my ($this, $parent, $context) = @_; |
|
721
|
4
|
|
|
|
|
5
|
my ($type2value, $name) = @{$this}; |
|
|
4
|
|
|
|
|
48
|
|
|
722
|
|
|
|
|
|
|
confess "generic type access outside a generic switch in $name" |
|
723
|
4
|
50
|
|
|
|
16
|
unless defined $parent->{Gencurtype}[-1]; |
|
724
|
4
|
|
|
|
|
15
|
$type2value->{$parent->{Gencurtype}[-1]->ppsym}; |
|
725
|
|
|
|
|
|
|
} |
|
726
|
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
728
|
|
|
|
|
|
|
PDL::PP::GentypeAccess; |
|
729
|
3
|
|
|
3
|
|
26
|
use Carp; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
946
|
|
|
730
|
|
|
|
|
|
|
|
|
731
|
0
|
|
|
0
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
|
|
0
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
|
|
733
|
0
|
|
|
0
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
|
734
|
|
|
|
|
|
|
confess "generic type access outside a generic switch" |
|
735
|
0
|
0
|
|
|
|
|
unless defined(my $type = $parent->{Gencurtype}[-1]); |
|
736
|
0
|
0
|
|
|
|
|
return $type->ctype if !$this->[0]; |
|
737
|
0
|
|
0
|
|
|
|
my $pobj = $parent->{ParObjs}{$this->[0]} // confess "not a defined parname"; |
|
738
|
0
|
|
|
|
|
|
$pobj->adjusted_type($type)->ctype; |
|
739
|
|
|
|
|
|
|
} |
|
740
|
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
package # hide from PAUSE/MetaCPAN |
|
742
|
|
|
|
|
|
|
PDL::PP::PpsymAccess; |
|
743
|
3
|
|
|
3
|
|
23
|
use Carp; |
|
|
3
|
|
|
|
|
49
|
|
|
|
3
|
|
|
|
|
1063
|
|
|
744
|
|
|
|
|
|
|
|
|
745
|
0
|
|
|
0
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
|
|
0
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
|
|
747
|
0
|
|
|
0
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
|
748
|
|
|
|
|
|
|
confess "generic type access outside a generic switch" |
|
749
|
0
|
0
|
|
|
|
|
unless defined(my $type = $parent->{Gencurtype}[-1]); |
|
750
|
0
|
0
|
|
|
|
|
return $type->ppsym if !$this->[0]; |
|
751
|
0
|
|
0
|
|
|
|
my $pobj = $parent->{ParObjs}{$this->[0]} // confess "not a defined parname"; |
|
752
|
0
|
|
|
|
|
|
$pobj->adjusted_type($type)->ppsym; |
|
753
|
|
|
|
|
|
|
} |
|
754
|
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
1; |