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 PDL::PP::Code; |
8
|
|
|
|
|
|
|
use Carp; |
9
|
|
|
|
|
|
|
our @CARP_NOT; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
use strict; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# check for bad value support |
14
|
|
|
|
|
|
|
# |
15
|
|
|
|
|
|
|
use PDL::Config; |
16
|
|
|
|
|
|
|
#use vars qw ( $bvalflag $usenan ); |
17
|
|
|
|
|
|
|
my $bvalflag = $PDL::Config{WITH_BADVAL} || 0; |
18
|
|
|
|
|
|
|
my $usenan = $PDL::Config{BADVAL_USENAN} || 0; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub get_pdls {my($this) = @_; return ($this->{ParNames},$this->{ParObjs});} |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# we define the method separate_code() at the end of this |
23
|
|
|
|
|
|
|
# file, so that it can call the constructors from the classes |
24
|
|
|
|
|
|
|
# defined in this file. ugly... |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# Do the appropriate substitutions in the code. |
27
|
|
|
|
|
|
|
sub new { |
28
|
|
|
|
|
|
|
my($type,$code,$badcode,$parnames,$parobjs,$indobjs,$generictypes, |
29
|
|
|
|
|
|
|
$extrageneric,$havethreading,$name, |
30
|
|
|
|
|
|
|
$dont_add_thrloop, $nogeneric_loop, $backcode ) = @_; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
die "Error: missing name argument to PDL::PP::Code->new call!\n" |
33
|
|
|
|
|
|
|
unless defined $name; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# simple way of handling bad code check |
36
|
|
|
|
|
|
|
$badcode = undef unless $bvalflag; |
37
|
|
|
|
|
|
|
my $handlebad = defined($badcode); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# last three arguments may not be supplied |
40
|
|
|
|
|
|
|
# (in fact, the nogeneric_loop argument may never be supplied now?) |
41
|
|
|
|
|
|
|
# |
42
|
|
|
|
|
|
|
# "backcode" is a flag to the PDL::PP::Threadloop class indicating thre threadloop |
43
|
|
|
|
|
|
|
# is for writeback code (typically used for writeback of data from child to parent PDL |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
$dont_add_thrloop = 0 unless defined $dont_add_thrloop; |
46
|
|
|
|
|
|
|
$nogeneric_loop = 0 unless defined $nogeneric_loop; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# C++ style comments |
50
|
|
|
|
|
|
|
# |
51
|
|
|
|
|
|
|
# This regexp isn't perfect because it doesn't cope with |
52
|
|
|
|
|
|
|
# literal string constants. |
53
|
|
|
|
|
|
|
# |
54
|
|
|
|
|
|
|
$code =~ s,//.*?\n,,g; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
if ($::PP_VERBOSE) { |
57
|
|
|
|
|
|
|
print "Processing code for $name\n"; |
58
|
|
|
|
|
|
|
print "DONT_ADD_THRLOOP!\n" if $dont_add_thrloop; |
59
|
|
|
|
|
|
|
print "EXTRAGEN: {" . |
60
|
|
|
|
|
|
|
join(" ", |
61
|
|
|
|
|
|
|
map { "$_=>" . $$extrageneric{$_}} keys %$extrageneric) |
62
|
|
|
|
|
|
|
. "}\n"; |
63
|
|
|
|
|
|
|
print "ParNAMES: ",(join ',',@$parnames),"\n"; |
64
|
|
|
|
|
|
|
print "GENTYPES: ", @$generictypes, "\n"; |
65
|
|
|
|
|
|
|
print "HandleBad: $handlebad\n"; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
my $this = bless { |
68
|
|
|
|
|
|
|
IndObjs => $indobjs, |
69
|
|
|
|
|
|
|
ParNames => $parnames, |
70
|
|
|
|
|
|
|
ParObjs => $parobjs, |
71
|
|
|
|
|
|
|
Gencurtype => [], # stack to hold GenType in generic loops |
72
|
|
|
|
|
|
|
types => 0, # hack for PDL::PP::Types/GenericLoop |
73
|
|
|
|
|
|
|
pars => {}, # hack for PDL::PP::NaNSupport/GenericLoop |
74
|
|
|
|
|
|
|
Generictypes => $generictypes, # so that MacroAccess can check it |
75
|
|
|
|
|
|
|
Name => $name, |
76
|
|
|
|
|
|
|
}, $type; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
my $inccode = join '',map {$_->get_incregisters();} (sort values %{$this->{ParObjs}}); |
79
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
# |
84
|
|
|
|
|
|
|
my ( $threadloops, $coderef, $sizeprivs ) = |
85
|
|
|
|
|
|
|
$this->separate_code( "{$inccode\n$code\n}" ); |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Now, if there is no explicit threadlooping in the code, |
88
|
|
|
|
|
|
|
# enclose everything into it. |
89
|
|
|
|
|
|
|
if(!$threadloops && !$dont_add_thrloop && $havethreading) { |
90
|
|
|
|
|
|
|
print "Adding threadloop...\n" if $::PP_VERBOSE; |
91
|
|
|
|
|
|
|
my $nc = $coderef; |
92
|
|
|
|
|
|
|
if( !$backcode ){ # Normal readbackdata threadloop |
93
|
|
|
|
|
|
|
$coderef = PDL::PP::ThreadLoop->new(); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
else{ # writebackcode threadloop |
96
|
|
|
|
|
|
|
$coderef = PDL::PP::BackCodeThreadLoop->new(); |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
push @{$coderef},$nc; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# repeat for the bad code, then stick good and bad into |
102
|
|
|
|
|
|
|
# a BadSwitch object which creates the necessary |
103
|
|
|
|
|
|
|
# 'if (bad) { badcode } else { goodcode }' code |
104
|
|
|
|
|
|
|
# |
105
|
|
|
|
|
|
|
# NOTE: amalgamate sizeprivs from good and bad code |
106
|
|
|
|
|
|
|
# |
107
|
|
|
|
|
|
|
if ( $handlebad ) { |
108
|
|
|
|
|
|
|
print "Processing 'bad' code...\n" if $::PP_VERBOSE; |
109
|
|
|
|
|
|
|
my ( $bad_threadloops, $bad_coderef, $bad_sizeprivs ) = |
110
|
|
|
|
|
|
|
$this->separate_code( "{$inccode\n$badcode\n}" ); |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
if(!$bad_threadloops && !$dont_add_thrloop && $havethreading) { |
113
|
|
|
|
|
|
|
print "Adding 'bad' threadloop...\n" if $::PP_VERBOSE; |
114
|
|
|
|
|
|
|
my $nc = $bad_coderef; |
115
|
|
|
|
|
|
|
if( !$backcode ){ # Normal readbackdata threadloop |
116
|
|
|
|
|
|
|
$bad_coderef = PDL::PP::ThreadLoop->new(); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
else{ # writebackcode threadloop |
119
|
|
|
|
|
|
|
$bad_coderef = PDL::PP::BackCodeThreadLoop->new(); |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
push @{$bad_coderef},$nc; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
my $good_coderef = $coderef; |
125
|
|
|
|
|
|
|
$coderef = PDL::PP::BadSwitch->new( $good_coderef, $bad_coderef ); |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# amalgamate sizeprivs from Code/BadCode segments |
128
|
|
|
|
|
|
|
# (sizeprivs is a simple hash, with each element |
129
|
|
|
|
|
|
|
# containing a string - see PDL::PP::Loop) |
130
|
|
|
|
|
|
|
while ( my ( $bad_key, $bad_str ) = each %$bad_sizeprivs ) { |
131
|
|
|
|
|
|
|
my $str = $$sizeprivs{$bad_key}; |
132
|
|
|
|
|
|
|
if ( defined $str ) { |
133
|
|
|
|
|
|
|
die "ERROR: sizeprivs problem in PP/PDLCode.pm (BadVal stuff)\n" |
134
|
|
|
|
|
|
|
unless $str eq $bad_str; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
$$sizeprivs{$bad_key} = $bad_str; # copy over |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
} # if: $handlebad |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
print "SIZEPRIVSX: ",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# Enclose it all in a genericloop. |
144
|
|
|
|
|
|
|
unless ($nogeneric_loop) { |
145
|
|
|
|
|
|
|
# XXX Make genericloop understand denied pointers;... |
146
|
|
|
|
|
|
|
my $nc = $coderef; |
147
|
|
|
|
|
|
|
$coderef = PDL::PP::GenericLoop->new($generictypes,"", |
148
|
|
|
|
|
|
|
[grep {!$extrageneric->{$_}} @$parnames],'$PRIV(__datatype)'); |
149
|
|
|
|
|
|
|
push @{$coderef},$nc; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# Do we have extra generic loops? |
153
|
|
|
|
|
|
|
# If we do, first reverse the hash: |
154
|
|
|
|
|
|
|
my %glh; |
155
|
|
|
|
|
|
|
for(keys %$extrageneric) { |
156
|
|
|
|
|
|
|
push @{$glh{$extrageneric->{$_}}},$_; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
my $no = 0; |
159
|
|
|
|
|
|
|
for(keys %glh) { |
160
|
|
|
|
|
|
|
my $nc = $coderef; |
161
|
|
|
|
|
|
|
$coderef = PDL::PP::GenericLoop->new($generictypes,$no++, |
162
|
|
|
|
|
|
|
$glh{$_},$_); |
163
|
|
|
|
|
|
|
push @$coderef,$nc; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# Then, in this form, put it together what we want the code to actually do. |
167
|
|
|
|
|
|
|
print "SIZEPRIVS: ",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
168
|
|
|
|
|
|
|
$this->{Code} = "{".(join '',sort values %$sizeprivs). |
169
|
|
|
|
|
|
|
$coderef->get_str($this,[]) |
170
|
|
|
|
|
|
|
."}"; |
171
|
|
|
|
|
|
|
$this->{Code}; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
} # new() |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# This sub determines the index name for this index. |
176
|
|
|
|
|
|
|
# For example, a(x,y) and x0 becomes [x,x0] |
177
|
|
|
|
|
|
|
sub make_loopind { my($this,$ind) = @_; |
178
|
|
|
|
|
|
|
my $orig = $ind; |
179
|
|
|
|
|
|
|
while(!$this->{IndObjs}{$ind}) { |
180
|
|
|
|
|
|
|
if(!((chop $ind) =~ /[0-9]/)) { |
181
|
|
|
|
|
|
|
confess("Index not found for $_ ($ind)!\n"); |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
return [$ind,$orig]; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
##################################################################### |
189
|
|
|
|
|
|
|
# |
190
|
|
|
|
|
|
|
# Encapsulate the parsing code objects |
191
|
|
|
|
|
|
|
# |
192
|
|
|
|
|
|
|
# All objects have two methods: |
193
|
|
|
|
|
|
|
# new - constructor |
194
|
|
|
|
|
|
|
# get_str - get the string to be put into the xsub. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
########################### |
197
|
|
|
|
|
|
|
# |
198
|
|
|
|
|
|
|
# Encapsulate a block |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
package PDL::PP::Block; |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub new { my($type) = @_; bless [],$type; } |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
sub myoffs { return 0; } |
205
|
|
|
|
|
|
|
sub myprelude {} |
206
|
|
|
|
|
|
|
sub myitem {return "";} |
207
|
|
|
|
|
|
|
sub mypostlude {} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub get_str { |
210
|
|
|
|
|
|
|
my ($this,$parent,$context) = @_; |
211
|
|
|
|
|
|
|
my $str = $this->myprelude($parent,$context); |
212
|
|
|
|
|
|
|
$str .= $this->get_str_int($parent,$context); |
213
|
|
|
|
|
|
|
$str .= $this->mypostlude($parent,$context); |
214
|
|
|
|
|
|
|
return $str; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub get_str_int { |
218
|
|
|
|
|
|
|
my ( $this, $parent, $context ) = @_; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
my $nth=0; |
221
|
|
|
|
|
|
|
my $str = ""; |
222
|
|
|
|
|
|
|
MYLOOP: while(1) { |
223
|
|
|
|
|
|
|
my $it = $this->myitem($parent,$nth); |
224
|
|
|
|
|
|
|
last MYLOOP if $nth and !$it; |
225
|
|
|
|
|
|
|
$str .= $it; |
226
|
|
|
|
|
|
|
$str .= (join '',map {ref $_ ? $_->get_str($parent,$context) : $_} |
227
|
|
|
|
|
|
|
@{$this}[$this->myoffs()..$#{$this}]); |
228
|
|
|
|
|
|
|
$nth++; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
return $str; |
231
|
|
|
|
|
|
|
} # get_str_int() |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
########################### |
234
|
|
|
|
|
|
|
# |
235
|
|
|
|
|
|
|
# Deal with bad code |
236
|
|
|
|
|
|
|
# - ie create something like |
237
|
|
|
|
|
|
|
# if ( badflag ) { badcode } else { goodcode } |
238
|
|
|
|
|
|
|
# |
239
|
|
|
|
|
|
|
package PDL::PP::BadSwitch; |
240
|
|
|
|
|
|
|
@PDL::PP::BadSwitch::ISA = "PDL::PP::Block"; |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub new { |
243
|
|
|
|
|
|
|
my($type,$good,$bad) = @_; |
244
|
|
|
|
|
|
|
return bless [$good,$bad], $type; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub get_str { |
248
|
|
|
|
|
|
|
my ($this,$parent,$context) = @_; |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
my $good = $this->[0]; |
251
|
|
|
|
|
|
|
my $bad = $this->[1]; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
my $str = PDL::PP::pp_line_numbers(__LINE__, "if ( \$PRIV(bvalflag) ) { PDL_COMMENT(\"** do 'bad' Code **\")\n"); |
254
|
|
|
|
|
|
|
$str .= "\n#define PDL_BAD_CODE\n"; |
255
|
|
|
|
|
|
|
$str .= $bad->get_str($parent,$context); |
256
|
|
|
|
|
|
|
$str .= "\n#undef PDL_BAD_CODE\n"; |
257
|
|
|
|
|
|
|
$str .= "} else { PDL_COMMENT(\"** else do 'good' Code **\")\n"; |
258
|
|
|
|
|
|
|
$str .= $good->get_str($parent,$context); |
259
|
|
|
|
|
|
|
$str .= "}\n"; |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
return $str; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
########################### |
265
|
|
|
|
|
|
|
# |
266
|
|
|
|
|
|
|
# Encapsulate a loop |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
package PDL::PP::Loop; |
269
|
|
|
|
|
|
|
@PDL::PP::Loop::ISA = "PDL::PP::Block"; |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub new { my($type,$args,$sizeprivs,$parent) = @_; |
272
|
|
|
|
|
|
|
my $this = bless [$args],$type; |
273
|
|
|
|
|
|
|
for(@{$this->[0]}) { |
274
|
|
|
|
|
|
|
print "SIZP $sizeprivs, $_\n" if $::PP_VERBOSE; |
275
|
|
|
|
|
|
|
my $i = $parent->make_loopind($_); |
276
|
|
|
|
|
|
|
$sizeprivs->{$i->[0]} = |
277
|
|
|
|
|
|
|
"register PDL_Indx __$i->[0]_size = \$PRIV(__$i->[0]_size);\n"; |
278
|
|
|
|
|
|
|
print "SP :",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
return $this; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub myoffs { return 1; } |
284
|
|
|
|
|
|
|
sub myprelude { my($this,$parent,$context) = @_; |
285
|
|
|
|
|
|
|
my $text = ""; my $i; |
286
|
|
|
|
|
|
|
push @$context, map { |
287
|
|
|
|
|
|
|
$i = $parent->make_loopind($_); |
288
|
|
|
|
|
|
|
# Used to be $PRIV(.._size) but now we have it in a register. |
289
|
|
|
|
|
|
|
$text .= "{PDL_COMMENT(\"Open $_\") register PDL_Indx $_; |
290
|
|
|
|
|
|
|
for($_=0; $_<(__$i->[0]_size); $_++) {"; |
291
|
|
|
|
|
|
|
$i; |
292
|
|
|
|
|
|
|
} @{$this->[0]}; |
293
|
|
|
|
|
|
|
return PDL::PP::pp_line_numbers(__LINE__, $text); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
sub mypostlude { my($this,$parent,$context) = @_; |
296
|
|
|
|
|
|
|
splice @$context, - ($#{$this->[0]}+1); |
297
|
|
|
|
|
|
|
return join '',map {"}} PDL_COMMENT(\"Close $_\")"} @{$this->[0]}; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
########################### |
301
|
|
|
|
|
|
|
# |
302
|
|
|
|
|
|
|
# Encapsulate a generic type loop |
303
|
|
|
|
|
|
|
# |
304
|
|
|
|
|
|
|
# we use the value of $parent->{types} [set by a PDL::PP::Types object] |
305
|
|
|
|
|
|
|
# to determine whether to define/undefine the THISISxxx macros |
306
|
|
|
|
|
|
|
# (makes the xs code easier to read) |
307
|
|
|
|
|
|
|
# |
308
|
|
|
|
|
|
|
package PDL::PP::GenericLoop; |
309
|
|
|
|
|
|
|
@PDL::PP::GenericLoop::ISA = "PDL::PP::Block"; |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# Types: BSULFD |
312
|
|
|
|
|
|
|
use PDL::Types ':All'; |
313
|
|
|
|
|
|
|
sub new { |
314
|
|
|
|
|
|
|
my($type,$types,$name,$varnames,$whattype) = @_; |
315
|
|
|
|
|
|
|
bless [(PDL::PP::get_generictyperecs($types)),$name,$varnames, |
316
|
|
|
|
|
|
|
$whattype],$type; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub myoffs {4} |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub myprelude { |
322
|
|
|
|
|
|
|
my($this,$parent,$context) = @_; |
323
|
|
|
|
|
|
|
push @{$parent->{Gencurtype}},'PDL_undef'; # so that $GENERIC can get at it |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# horrible hack for PDL::PP::NaNSupport |
326
|
|
|
|
|
|
|
if ( $this->[1] ne "" ) { |
327
|
|
|
|
|
|
|
my ( @test ) = keys %{$parent->{pars}}; |
328
|
|
|
|
|
|
|
die "ERROR: need to rethink NaNSupport in GenericLoop\n" |
329
|
|
|
|
|
|
|
if $#test != -1; |
330
|
|
|
|
|
|
|
$parent->{pars} = {}; |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
my $thisis_loop = ''; |
334
|
|
|
|
|
|
|
if ( $parent->{types} ) { |
335
|
|
|
|
|
|
|
$thisis_loop = join '', |
336
|
|
|
|
|
|
|
map { |
337
|
|
|
|
|
|
|
"#undef THISIS$this->[1]_$_\n#define THISIS$this->[1]_$_(a)\n" |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
(ppdefs); |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
return <
|
343
|
|
|
|
|
|
|
PDL_COMMENT("Start generic loop") |
344
|
|
|
|
|
|
|
$thisis_loop |
345
|
|
|
|
|
|
|
switch($this->[3]) { case -42: PDL_COMMENT("Warning eater") {(void)1; |
346
|
|
|
|
|
|
|
WARNING_EATER |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
sub myitem { |
350
|
|
|
|
|
|
|
my($this,$parent,$nth) = @_; |
351
|
|
|
|
|
|
|
# print "GENERICITEM\n"; |
352
|
|
|
|
|
|
|
my $item = $this->[0]->[$nth]; |
353
|
|
|
|
|
|
|
if(!$item) {return "";} |
354
|
|
|
|
|
|
|
$parent->{Gencurtype}->[-1] = $item->[1]; |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
# horrible hack for PDL::PP::NaNSupport |
357
|
|
|
|
|
|
|
if ( $this->[1] ne "" ) { |
358
|
|
|
|
|
|
|
foreach my $parname ( @{$this->[2]} ) { |
359
|
|
|
|
|
|
|
$parent->{pars}{$parname} = $item->[1]; |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
my $thisis_loop = ''; |
364
|
|
|
|
|
|
|
if ( $parent->{types} ) { |
365
|
|
|
|
|
|
|
$thisis_loop = ( |
366
|
|
|
|
|
|
|
join '', |
367
|
|
|
|
|
|
|
map { |
368
|
|
|
|
|
|
|
"#undef THISIS$this->[1]_$_\n#define THISIS$this->[1]_$_(a)\n"; |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
(ppdefs) |
371
|
|
|
|
|
|
|
) . |
372
|
|
|
|
|
|
|
"#undef THISIS$this->[1]_$item->[3]\n" . |
373
|
|
|
|
|
|
|
"#define THISIS$this->[1]_$item->[3](a) a\n"; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
return PDL::PP::pp_line_numbers(__LINE__, "\t} break; case $item->[0]: {\n". |
377
|
0
|
|
|
|
|
|
$thisis_loop . |
378
|
|
|
|
|
|
|
(join '',map{ |
379
|
|
|
|
|
|
|
# print "DAPAT: '$_'\n"; |
380
|
|
|
|
|
|
|
$parent->{ParObjs}{$_}->get_xsdatapdecl($item->[1]); |
381
|
|
|
|
|
|
|
} (@{$this->[2]}))); |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
sub mypostlude { |
385
|
|
|
|
|
|
|
my($this,$parent,$context) = @_; |
386
|
|
|
|
|
|
|
pop @{$parent->{Gencurtype}}; # and clean up the Gentype stack |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
# horrible hack for PDL::PP::NaNSupport |
389
|
|
|
|
|
|
|
if ( $this->[1] ne "" ) { $parent->{pars} = {}; } |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
return "\tbreak;} |
392
|
|
|
|
|
|
|
default:barf(\"PP INTERNAL ERROR! PLEASE MAKE A BUG REPORT\\n\");}\n"; |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
########################### |
397
|
|
|
|
|
|
|
# |
398
|
|
|
|
|
|
|
# Encapsulate a threadloop. |
399
|
|
|
|
|
|
|
# There are several different |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
package PDL::PP::ThreadLoop; |
402
|
|
|
|
|
|
|
sub new { |
403
|
|
|
|
|
|
|
return PDL::PP::ComplexThreadLoop->new(@_); |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
package PDL::PP::SimpleThreadLoop; |
407
|
|
|
|
|
|
|
use Carp; |
408
|
|
|
|
|
|
|
@PDL::PP::SimpleThreadLoop::ISA = "PDL::PP::Block"; |
409
|
|
|
|
|
|
|
our @CARP_NOT; |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub new { my($type) = @_; bless [],$type; } |
412
|
|
|
|
|
|
|
sub myoffs { return 0; } |
413
|
|
|
|
|
|
|
sub myprelude {my($this,$parent,$context) = @_; |
414
|
|
|
|
|
|
|
my $no; |
415
|
|
|
|
|
|
|
my ($ord,$pdls) = $parent->get_pdls(); |
416
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, ' PDL_COMMENT("THREADLOOPBEGIN") |
417
|
|
|
|
|
|
|
if(PDL->startthreadloop(&($PRIV(__pdlthread)),$PRIV(vtable)->readdata, |
418
|
|
|
|
|
|
|
__privtrans))) return; |
419
|
|
|
|
|
|
|
do { |
420
|
|
|
|
|
|
|
'.(join '',map {"${_}_datap += \$PRIV(__pdlthread).offs[".(0+$no++)."];\n"} |
421
|
|
|
|
|
|
|
@$ord).' |
422
|
|
|
|
|
|
|
'); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
sub mypostlude {my($this,$parent,$context) = @_; |
426
|
|
|
|
|
|
|
my $no; |
427
|
|
|
|
|
|
|
my ($ord,$pdls) = $parent->get_pdls(); |
428
|
|
|
|
|
|
|
' PDL_COMMENT("THREADLOOPEND") |
429
|
|
|
|
|
|
|
'.(join '',map {"${_}_datap -= \$PRIV(__pdlthread).offs[".(0+$no++)."];\n"} |
430
|
|
|
|
|
|
|
@$ord).' |
431
|
|
|
|
|
|
|
} while(PDL->iterthreadloop(&$PRIV(__pdlthread),0)); |
432
|
|
|
|
|
|
|
' |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
#### |
436
|
|
|
|
|
|
|
# |
437
|
|
|
|
|
|
|
# This relies on PP.pm making sure that initthreadloop always sets |
438
|
|
|
|
|
|
|
# up the two first dimensions even when they are not necessary. |
439
|
|
|
|
|
|
|
# |
440
|
|
|
|
|
|
|
package PDL::PP::ComplexThreadLoop; |
441
|
|
|
|
|
|
|
use Carp; |
442
|
|
|
|
|
|
|
@PDL::PP::ComplexThreadLoop::ISA = "PDL::PP::Block"; |
443
|
|
|
|
|
|
|
our @CARP_NOT; |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub new { |
447
|
|
|
|
|
|
|
my $type = shift; |
448
|
|
|
|
|
|
|
bless [],$type; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
sub myoffs { return 0; } |
451
|
|
|
|
|
|
|
sub myprelude { |
452
|
|
|
|
|
|
|
my($this,$parent,$context, $backcode) = @_; |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# Set appropriate function from the vtable to supply to threadthreadloop. |
455
|
|
|
|
|
|
|
# Function name from the vtable is readdata for normal code |
456
|
|
|
|
|
|
|
# function name for backcode is writebackdata |
457
|
|
|
|
|
|
|
my $funcName = "readdata"; |
458
|
|
|
|
|
|
|
$funcName = "writebackdata" if( $backcode ); |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
my ($ord,$pdls) = $parent->get_pdls(); |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, join "\n ", |
463
|
|
|
|
|
|
|
'', |
464
|
|
|
|
|
|
|
'PDL_COMMENT("THREADLOOPBEGIN")', |
465
|
14
|
0
|
|
|
|
|
'if ( PDL->startthreadloop(&($PRIV(__pdlthread)),$PRIV(vtable)->'.$funcName.', __tr) ) return; |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
466
|
14
|
|
|
|
|
|
do { register PDL_Indx __tind1=0,__tind2=0; |
467
|
14
|
|
|
|
|
|
register PDL_Indx __tnpdls = $PRIV(__pdlthread).npdls; |
468
|
14
|
|
|
|
|
|
register PDL_Indx __tdims1 = $PRIV(__pdlthread.dims[1]); |
469
|
14
|
|
|
|
|
|
register PDL_Indx __tdims0 = $PRIV(__pdlthread.dims[0]); |
470
|
14
|
|
|
|
|
|
register PDL_Indx *__offsp = PDL->get_threadoffsp(&$PRIV(__pdlthread));', |
471
|
14
|
|
|
|
|
|
( map { "register PDL_Indx __tinc0_${_} = \$PRIV(__pdlthread).incs[${_}];"} 0..$#{$ord}), |
472
|
14
|
|
|
|
|
|
( map { "register PDL_Indx __tinc1_${_} = \$PRIV(__pdlthread).incs[__tnpdls+$_];"} 0.. $#{$ord}), |
473
|
14
|
|
|
|
|
|
( map { $ord->[$_] ."_datap += __offsp[$_];"} 0..$#{$ord} ), |
474
|
22
|
0
|
|
|
|
|
'for( __tind2 = 0 ; |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
475
|
|
|
|
|
|
|
__tind2 < __tdims1 ; |
476
|
8
|
|
|
|
|
|
__tind2++', |
477
|
8
|
|
|
|
|
|
( map { "\t\t," . $ord->[$_] . "_datap += __tinc1_${_} - __tinc0_${_} * __tdims0"} 0..$#{$ord} ), |
478
|
|
|
|
|
|
|
')', |
479
|
|
|
|
|
|
|
'{ |
480
|
22
|
0
|
|
|
|
|
for( __tind1 = 0 ; |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
481
|
|
|
|
|
|
|
__tind1 < __tdims0 ; |
482
|
8
|
|
|
|
|
|
__tind1++', |
483
|
8
|
|
|
|
|
|
( map { "\t\t," . $ord->[$_] . "_datap += __tinc0_${_}"} 0..$#{$ord}), |
484
|
|
|
|
|
|
|
')', |
485
|
|
|
|
|
|
|
'{ PDL_COMMENT("This is the tightest threadloop. Make sure inside is optimal.")' |
486
|
14
|
|
|
|
|
|
); |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
|
489
|
14
|
|
|
|
|
|
# Should possibly fold out thread.dims[0] and [1]. |
490
|
14
|
|
|
|
|
|
sub mypostlude {my($this,$parent,$context) = @_; |
491
|
|
|
|
|
|
|
|
492
|
14
|
0
|
|
|
|
|
my ($ord,$pdls) = $parent->get_pdls(); |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
493
|
27
|
0
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, join "\n ", |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
494
|
21
|
|
|
|
|
|
'', |
495
|
21
|
0
|
|
|
|
|
'PDL_COMMENT("THREADLOOPEND")', |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
496
|
2
|
|
|
|
|
|
'}', |
497
|
|
|
|
|
|
|
'}', |
498
|
8
|
|
|
|
|
|
( map { $ord->[$_] . "_datap -= __tinc1_${_} * __tdims1 + __offsp[${_}];"} 0..$#{$ord} ), |
499
|
14
|
0
|
|
|
|
|
'} while(PDL->iterthreadloop(&$PRIV(__pdlthread),2));' |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
500
|
19
|
0
|
|
|
|
|
) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
501
|
0
|
|
|
|
|
|
} |
502
|
9
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
503
|
2
|
|
|
|
|
|
# Simple subclass of ComplexThreadLoop to implement writeback code |
504
|
|
|
|
|
|
|
# |
505
|
|
|
|
|
|
|
# |
506
|
|
|
|
|
|
|
package PDL::PP::BackCodeThreadLoop; |
507
|
2
|
|
|
|
|
|
use Carp; |
508
|
|
|
|
|
|
|
@PDL::PP::BackCodeThreadLoop::ISA = "PDL::PP::ComplexThreadLoop"; |
509
|
8
|
|
|
|
|
|
our @CARP_NOT; |
510
|
|
|
|
|
|
|
|
511
|
8
|
|
|
|
|
|
sub myprelude { |
512
|
|
|
|
|
|
|
my($this,$parent,$context, $backcode) = @_; |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
# Set backcode flag if not defined. This will make the parent |
515
|
|
|
|
|
|
|
# myprelude emit proper writeback code |
516
|
|
|
|
|
|
|
$backcode = 1 unless defined($backcode); |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
$this->SUPER::myprelude($parent, $context, $backcode); |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
########################### |
523
|
|
|
|
|
|
|
# |
524
|
|
|
|
|
|
|
# Encapsulate a types() switch |
525
|
|
|
|
|
|
|
# |
526
|
|
|
|
|
|
|
# horrible hack: |
527
|
|
|
|
|
|
|
# set $parent->{types} if we create this object so that |
528
|
|
|
|
|
|
|
# PDL::PP::GenericLoop knows to define the THISIS ... macros |
529
|
|
|
|
|
|
|
# |
530
|
|
|
|
|
|
|
package PDL::PP::Types; |
531
|
|
|
|
|
|
|
use Carp; |
532
|
|
|
|
|
|
|
use PDL::Types ':All'; |
533
|
|
|
|
|
|
|
@PDL::PP::Types::ISA = "PDL::PP::Block"; |
534
|
|
|
|
|
|
|
our @CARP_NOT; |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
sub new { |
537
|
|
|
|
|
|
|
my($type,$ts,$parent) = @_; |
538
|
|
|
|
|
|
|
my $types = join '', ppdefs; # BSUL.... |
539
|
|
|
|
|
|
|
$ts =~ /[$types]+/ or confess "Invalid type access with '$ts'!"; |
540
|
|
|
|
|
|
|
$parent->{types} = 1; # hack for PDL::PP::GenericLoop |
541
|
|
|
|
|
|
|
bless [$ts],$type; } |
542
|
|
|
|
|
|
|
sub myoffs { return 1; } |
543
|
|
|
|
|
|
|
sub myprelude { |
544
|
|
|
|
|
|
|
my($this,$parent,$context) = @_; |
545
|
|
|
|
|
|
|
return "\n#if ". (join '||',map {"(THISIS_$_(1)+0)"} split '',$this->[0])."\n"; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
sub mypostlude {my($this,$parent,$context) = @_; |
549
|
|
|
|
|
|
|
"\n#endif\n" |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
########################### |
554
|
|
|
|
|
|
|
# |
555
|
|
|
|
|
|
|
# Encapsulate an access |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
package PDL::PP::Access; |
558
|
|
|
|
|
|
|
use Carp; |
559
|
|
|
|
|
|
|
our @CARP_NOT; |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
sub new { my($type,$str,$parent) = @_; |
562
|
|
|
|
|
|
|
$str =~ /^\$([a-zA-Z_]\w*)\s*\(([^)]*)\)/ or |
563
|
|
|
|
|
|
|
confess ("Access wrong: '$str'\n"); |
564
|
|
|
|
|
|
|
my($pdl,$inds) = ($1,$2); |
565
|
|
|
|
|
|
|
if($pdl =~ /^T/) {new PDL::PP::MacroAccess($pdl,$inds, |
566
|
|
|
|
|
|
|
$parent->{Generictypes},$parent->{Name});} |
567
|
|
|
|
|
|
|
elsif($pdl =~ /^P$/) {new PDL::PP::PointerAccess($pdl,$inds);} |
568
|
|
|
|
|
|
|
elsif($pdl =~ /^PP$/) {new PDL::PP::PhysPointerAccess($pdl,$inds);} |
569
|
|
|
|
|
|
|
elsif($pdl =~ /^SIZE$/) {new PDL::PP::SizeAccess($pdl,$inds);} |
570
|
|
|
|
|
|
|
elsif($pdl =~ /^RESIZE$/) {new PDL::PP::ReSizeAccess($pdl,$inds);} |
571
|
|
|
|
|
|
|
elsif($pdl =~ /^GENERIC$/) {new PDL::PP::GentypeAccess($pdl,$inds);} |
572
|
|
|
|
|
|
|
elsif($pdl =~ /^PDL$/) {new PDL::PP::PdlAccess($pdl,$inds);} |
573
|
|
|
|
|
|
|
elsif(!defined $parent->{ParObjs}{$pdl}) {new PDL::PP::OtherAccess($pdl,$inds);} |
574
|
|
|
|
|
|
|
else { |
575
|
|
|
|
|
|
|
bless [$pdl,$inds],$type; |
576
|
|
|
|
|
|
|
} |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub get_str { my($this,$parent,$context) = @_; |
580
|
|
|
|
|
|
|
# print "AC: $this->[0]\n"; |
581
|
|
|
|
|
|
|
$parent->{ParObjs}{$this->[0]}->do_access($this->[1],$context) |
582
|
|
|
|
|
|
|
if defined($parent->{ParObjs}{$this->[0]}); |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
########################### |
586
|
|
|
|
|
|
|
# |
587
|
|
|
|
|
|
|
# Just some other substituted thing. |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
package PDL::PP::OtherAccess; |
590
|
|
|
|
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$pdl,$inds],$type; } |
591
|
|
|
|
|
|
|
sub get_str {my($this) = @_;return "\$$this->[0]($this->[1])"} |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
########################### |
595
|
|
|
|
|
|
|
# |
596
|
|
|
|
|
|
|
# used by BadAccess code to know when to use NaN support |
597
|
|
|
|
|
|
|
# - the output depends on the value of the |
598
|
|
|
|
|
|
|
# BADVAL_USENAN option in perldl.conf |
599
|
|
|
|
|
|
|
# == 1 then we use NaN's |
600
|
|
|
|
|
|
|
# 0 PDL.bvals.Float/Double |
601
|
|
|
|
|
|
|
# |
602
|
|
|
|
|
|
|
# note the *horrible hack* for piddles whose type have been |
603
|
|
|
|
|
|
|
# specified using the FType option - see GenericLoop. |
604
|
|
|
|
|
|
|
# There MUST be a better way than this... |
605
|
|
|
|
|
|
|
# |
606
|
|
|
|
|
|
|
package PDL::PP::NaNSupport; |
607
|
|
|
|
|
|
|
use PDL::Types ':All'; # typefld et al. |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
# need to be lower-case because of FlagTyped stuff |
610
|
|
|
|
|
|
|
# |
611
|
|
|
|
|
|
|
# need to be able to handle signatures with fixed types |
612
|
|
|
|
|
|
|
# which means parameters like 'int mask()', |
613
|
|
|
|
|
|
|
# which means the hack to add 'int' to %use_nan |
614
|
|
|
|
|
|
|
# |
615
|
|
|
|
|
|
|
my %use_nan = |
616
|
|
|
|
|
|
|
map {(typefld($_,'convertfunc') => typefld($_,'usenan')*$usenan)} typesrtkeys; |
617
|
|
|
|
|
|
|
$use_nan{int} = 0; |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
# original try |
620
|
|
|
|
|
|
|
##my %use_nan = |
621
|
|
|
|
|
|
|
## map {(typefld($_,'convertfunc') => typefld($_,'usenan')*$usenan)} typesrtkeys; |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
# Was the following, before new Type "interface" |
624
|
|
|
|
|
|
|
# ( byte => 0, short => 0, ushort => 0, long => 0, |
625
|
|
|
|
|
|
|
# int => 0, longlong => 0, # necessary for fixed-type piddles (or something) |
626
|
|
|
|
|
|
|
# float => $usenan, |
627
|
|
|
|
|
|
|
# double => $usenan |
628
|
|
|
|
|
|
|
# ); |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
my %set_nan = |
631
|
|
|
|
|
|
|
( |
632
|
|
|
|
|
|
|
float => 'PDL->bvals.Float', PDL_Float => 'PDL->bvals.Float', |
633
|
|
|
|
|
|
|
double => 'PDL->bvals.Double', PDL_Double => 'PDL->bvals.Double', |
634
|
|
|
|
|
|
|
); |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
sub use_nan ($) { |
637
|
|
|
|
|
|
|
my $type = shift; |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
$type =~ s/^PDL_//; |
640
|
|
|
|
|
|
|
$type = lc $type; |
641
|
|
|
|
|
|
|
die "ERROR: Unknown type [$type] used in a 'Bad' macro." |
642
|
|
|
|
|
|
|
unless exists $use_nan{$type}; |
643
|
|
|
|
|
|
|
return $use_nan{$type}; |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
sub convert ($$$$$) { |
647
|
|
|
|
|
|
|
my ( $parent, $name, $lhs, $rhs, $opcode ) = @_; |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
my $type = $parent->{Gencurtype}[-1]; |
650
|
|
|
|
|
|
|
die "ERROR: unable to find type info for $opcode access" |
651
|
|
|
|
|
|
|
unless defined $type; |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
# note: gentype may not be sensible because the |
654
|
|
|
|
|
|
|
# actual piddle could have a 'fixed' type |
655
|
|
|
|
|
|
|
die "ERROR: unable to find piddle $name in parent!" |
656
|
|
|
|
|
|
|
unless exists $parent->{ParObjs}{$name}; |
657
|
|
|
|
|
|
|
my $pobj = $parent->{ParObjs}{$name}; |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
# based on code from from PdlParObj::ctype() |
660
|
|
|
|
|
|
|
# - want to handle FlagTplus case |
661
|
|
|
|
|
|
|
# - may not be correct |
662
|
|
|
|
|
|
|
# - extended to include hack to GenericLoop |
663
|
|
|
|
|
|
|
# |
664
|
|
|
|
|
|
|
if ( exists $parent->{pars}{$name} ) { |
665
|
|
|
|
|
|
|
$type = $parent->{pars}{$name}; |
666
|
|
|
|
|
|
|
print "#DBG: hacked <$name> to type <$type>\n" if $::PP_VERBOSE; |
667
|
|
|
|
|
|
|
} elsif ( exists $pobj->{FlagTyped} and $pobj->{FlagTyped} ) { |
668
|
|
|
|
|
|
|
$type = $pobj->{Type}; |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
# this should use Dev.pm - fortunately only worried about double/float here |
671
|
|
|
|
|
|
|
# XXX - do I really know what I'm doing ? |
672
|
|
|
|
|
|
|
if ( $pobj->{FlagTplus} ) { |
673
|
|
|
|
|
|
|
my $gtype = $parent->{Gencurtype}[-1]; |
674
|
|
|
|
|
|
|
if ( $gtype eq "PDL_Double" ) { |
675
|
|
|
|
|
|
|
$type = $gtype if $type ne "double"; |
676
|
|
|
|
|
|
|
} elsif ( $gtype eq "PDL_Float" ) { |
677
|
|
|
|
|
|
|
$type = $gtype if $type !~ /^(float|double)$/; # note: ignore doubles |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
} |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
if ( use_nan($type) ) { |
683
|
|
|
|
|
|
|
if ( $opcode eq "SETBAD" ) { |
684
|
|
|
|
|
|
|
# $rhs = "(0.0/0.0)"; |
685
|
|
|
|
|
|
|
$rhs = $set_nan{$type}; |
686
|
|
|
|
|
|
|
} else { |
687
|
|
|
|
|
|
|
$rhs = "0"; |
688
|
|
|
|
|
|
|
$lhs = "finite($lhs)"; |
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
return ( $lhs, $rhs ); |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
########################### |
696
|
|
|
|
|
|
|
# |
697
|
|
|
|
|
|
|
# Encapsulate a check on whether a value is good or bad |
698
|
|
|
|
|
|
|
# handles both checking (good/bad) and setting (bad) |
699
|
|
|
|
|
|
|
# |
700
|
|
|
|
|
|
|
# Integer types (BSUL) + floating point when no NaN (FD) |
701
|
|
|
|
|
|
|
# $ISBAD($a(n)) -> $a(n) == a_badval |
702
|
|
|
|
|
|
|
# $ISGOOD($a()) $a() != a_badval |
703
|
|
|
|
|
|
|
# $SETBAD($a()) $a() = a_badval |
704
|
|
|
|
|
|
|
# |
705
|
|
|
|
|
|
|
# floating point with NaN |
706
|
|
|
|
|
|
|
# $ISBAD($a(n)) -> finite($a(n)) == 0 |
707
|
|
|
|
|
|
|
# $ISGOOD($a()) finite($a()) != 0 |
708
|
|
|
|
|
|
|
# $SETBAD($a()) $a() = PDL->bvals.Float (or .Double) |
709
|
|
|
|
|
|
|
# |
710
|
|
|
|
|
|
|
# I've also got it so that the $ on the pdl name is not |
711
|
|
|
|
|
|
|
# necessary - so $ISBAD(a(n)) is also accepted, so as to reduce the |
712
|
|
|
|
|
|
|
# amount of line noise. This is actually done by the regexp |
713
|
|
|
|
|
|
|
# in the separate_code() sub at the end of the file. |
714
|
|
|
|
|
|
|
# |
715
|
|
|
|
|
|
|
# note: |
716
|
|
|
|
|
|
|
# we also expand out $a(n) etc as well here |
717
|
|
|
|
|
|
|
# |
718
|
|
|
|
|
|
|
# To do: |
719
|
|
|
|
|
|
|
# need to allow use of F,D without NaN |
720
|
|
|
|
|
|
|
# |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
package PDL::PP::BadAccess; |
723
|
|
|
|
|
|
|
use Carp; |
724
|
|
|
|
|
|
|
our @CARP_NOT; |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
sub new { |
727
|
|
|
|
|
|
|
my ( $type, $opcode, $pdl_name, $inds, $parent ) = @_; |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
# trying to avoid auto creation of hash elements |
730
|
|
|
|
|
|
|
my $check = $parent->{ParObjs}; |
731
|
|
|
|
|
|
|
die "\nIt looks like you have tried a \$${opcode}() macro on an\n" . |
732
|
|
|
|
|
|
|
" unknown piddle <$pdl_name($inds)>\n" |
733
|
|
|
|
|
|
|
unless exists($check->{$pdl_name}) and defined($check->{$pdl_name}); |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
return bless [$opcode, $pdl_name, $inds], $type; |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
our %ops = ( ISBAD => '==', ISGOOD => '!=', SETBAD => '=' ); |
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
sub get_str { |
741
|
|
|
|
|
|
|
my($this,$parent,$context) = @_; |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
my $opcode = $this->[0]; |
744
|
|
|
|
|
|
|
my $name = $this->[1]; |
745
|
|
|
|
|
|
|
my $inds = $this->[2]; |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
print "PDL::PP::BadAccess sent [$opcode] [$name] [$inds]\n" if $::PP_VERBOSE; |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
my $op = $ops{$opcode}; |
750
|
|
|
|
|
|
|
die "ERROR: unknown check <$opcode> sent to PDL::PP::BadAccess\n" |
751
|
|
|
|
|
|
|
unless defined $op; |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
my $obj = $parent->{ParObjs}{$name}; |
754
|
|
|
|
|
|
|
die "ERROR: something screwy in PDL::PP::BadAccess (PP/PDLCode.pm)\n" |
755
|
|
|
|
|
|
|
unless defined( $obj ); |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
my $lhs = $obj->do_access($inds,$context); |
758
|
|
|
|
|
|
|
my $rhs = "${name}_badval"; |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
( $lhs, $rhs ) = |
761
|
|
|
|
|
|
|
PDL::PP::NaNSupport::convert( $parent, $name, $lhs, $rhs, $opcode ); |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
print "DBG: [$lhs $op $rhs]\n" if $::PP_VERBOSE; |
764
|
|
|
|
|
|
|
return "$lhs $op $rhs"; |
765
|
|
|
|
|
|
|
} |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
########################### |
769
|
|
|
|
|
|
|
# |
770
|
|
|
|
|
|
|
# Encapsulate a check on whether a value is good or bad |
771
|
|
|
|
|
|
|
# handles both checking (good/bad) and setting (bad) |
772
|
|
|
|
|
|
|
# |
773
|
|
|
|
|
|
|
# Integer types (BSUL) + floating point when no NaN (FD) |
774
|
|
|
|
|
|
|
# $ISBADVAR(foo,a) -> foo == a_badval |
775
|
|
|
|
|
|
|
# $ISGOODVAR(foo,a) foo != a_badval |
776
|
|
|
|
|
|
|
# $SETBADVAR(foo,a) foo = a_badval |
777
|
|
|
|
|
|
|
# |
778
|
|
|
|
|
|
|
# floating point with NaN |
779
|
|
|
|
|
|
|
# $ISBADVAR(foo,a) -> finite(foo) == 0 |
780
|
|
|
|
|
|
|
# $ISGOODVAR(foo,a) finite(foo) != 0 |
781
|
|
|
|
|
|
|
# $SETBADVAR(foo,a) foo = PDL->bvals.Float (or .Double) |
782
|
|
|
|
|
|
|
# |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
package PDL::PP::BadVarAccess; |
785
|
|
|
|
|
|
|
use Carp; |
786
|
|
|
|
|
|
|
our @CARP_NOT; |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
sub new { |
789
|
|
|
|
|
|
|
my ( $type, $opcode, $var_name, $pdl_name, $parent ) = @_; |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
# trying to avoid auto creation of hash elements |
792
|
|
|
|
|
|
|
my $check = $parent->{ParObjs}; |
793
|
|
|
|
|
|
|
die "\nIt looks like you have tried a \$${opcode}() macro on an\n" . |
794
|
|
|
|
|
|
|
" unknown piddle <$pdl_name>\n" |
795
|
|
|
|
|
|
|
unless exists($check->{$pdl_name}) and defined($check->{$pdl_name}); |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
bless [$opcode, $var_name, $pdl_name], $type; |
798
|
|
|
|
|
|
|
} |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
our %ops = ( ISBAD => '==', ISGOOD => '!=', SETBAD => '=' ); |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
sub get_str { |
803
|
|
|
|
|
|
|
my($this,$parent,$context) = @_; |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
my $opcode = $this->[0]; |
806
|
|
|
|
|
|
|
my $var_name = $this->[1]; |
807
|
|
|
|
|
|
|
my $pdl_name = $this->[2]; |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
print "PDL::PP::BadVarAccess sent [$opcode] [$var_name] [$pdl_name]\n" if $::PP_VERBOSE; |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
my $op = $ops{$opcode}; |
812
|
|
|
|
|
|
|
die "ERROR: unknown check <$opcode> sent to PDL::PP::BadVarAccess\n" |
813
|
|
|
|
|
|
|
unless defined $op; |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
my $obj = $parent->{ParObjs}{$pdl_name}; |
816
|
|
|
|
|
|
|
die "ERROR: something screwy in PDL::PP::BadVarAccess (PP/PDLCode.pm)\n" |
817
|
|
|
|
|
|
|
unless defined( $obj ); |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
my $lhs = $var_name; |
820
|
|
|
|
|
|
|
my $rhs = "${pdl_name}_badval"; |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
( $lhs, $rhs ) = |
823
|
|
|
|
|
|
|
PDL::PP::NaNSupport::convert( $parent, $pdl_name, $lhs, $rhs, $opcode ); |
824
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
print "DBG: [$lhs $op $rhs]\n" if $::PP_VERBOSE; |
826
|
|
|
|
|
|
|
return "$lhs $op $rhs"; |
827
|
|
|
|
|
|
|
} |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
########################### |
831
|
|
|
|
|
|
|
# |
832
|
|
|
|
|
|
|
# Encapsulate a check on whether a value is good or bad using PP |
833
|
|
|
|
|
|
|
# handles both checking (good/bad) and setting (bad) |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
# this is only an initial attempt - it will, almost certainly, |
836
|
|
|
|
|
|
|
# need more work as more code is converted to handle bad values |
837
|
|
|
|
|
|
|
# |
838
|
|
|
|
|
|
|
# currently it can only handle cases like |
839
|
|
|
|
|
|
|
# $PPISBAD(PARENT,[i]) -> PARENT_physdatap[i] == PARENT_badval |
840
|
|
|
|
|
|
|
# etc |
841
|
|
|
|
|
|
|
# |
842
|
|
|
|
|
|
|
# if we use NaN's, then |
843
|
|
|
|
|
|
|
# $PPISBAD(PARENT,[i]) -> finite(PARENT_physdatap[i]) == 0 |
844
|
|
|
|
|
|
|
# $PPISGOOD(PARENT,[i]) -> finite(PARENT_physdatap[i]) != 0 |
845
|
|
|
|
|
|
|
# $PPSETBAD(PARENT,[i]) -> PARENT_physdatap[i] = PDL->bvals.Float (or .Double) |
846
|
|
|
|
|
|
|
# |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
package PDL::PP::PPBadAccess; |
849
|
|
|
|
|
|
|
use Carp; |
850
|
|
|
|
|
|
|
our @CARP_NOT; |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
sub new { |
853
|
|
|
|
|
|
|
my ( $type, $opcode, $pdl_name, $inds, $parent ) = @_; |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
$opcode =~ s/^PP//; |
856
|
|
|
|
|
|
|
bless [$opcode, $pdl_name, $inds], $type; |
857
|
|
|
|
|
|
|
} |
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
# PP is stripped in new() |
860
|
|
|
|
|
|
|
our %ops = ( ISBAD => '==', ISGOOD => '!=', SETBAD => '=' ); |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
sub get_str { |
863
|
|
|
|
|
|
|
my($this,$parent,$context) = @_; |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
my $opcode = $this->[0]; |
866
|
|
|
|
|
|
|
my $name = $this->[1]; |
867
|
|
|
|
|
|
|
my $inds = $this->[2]; |
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
print "PDL::PP::PPBadAccess sent [$opcode] [$name] [$inds]\n" if $::PP_VERBOSE; |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
my $op = $ops{$opcode}; |
872
|
|
|
|
|
|
|
die "\nERROR: unknown check <$opcode> sent to PDL::PP::PPBadAccess\n" |
873
|
|
|
|
|
|
|
unless defined $op; |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
my $obj = $parent->{ParObjs}{$name}; |
876
|
|
|
|
|
|
|
die "\nERROR: ParObjs does not seem to exist for <$name> = problem in PDL::PP::PPBadAccess\n" |
877
|
|
|
|
|
|
|
unless defined $obj; |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
my $lhs = $obj->do_physpointeraccess() . "$inds"; |
880
|
|
|
|
|
|
|
my $rhs = "${name}_badval"; |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
( $lhs, $rhs ) = |
883
|
|
|
|
|
|
|
PDL::PP::NaNSupport::convert( $parent, $name, $lhs, $rhs, $opcode ); |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
print "DBG: [$lhs $op $rhs]\n" if $::PP_VERBOSE; |
886
|
|
|
|
|
|
|
return "$lhs $op $rhs"; |
887
|
|
|
|
|
|
|
} |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
########################### |
891
|
|
|
|
|
|
|
# |
892
|
|
|
|
|
|
|
# Encapsulate a check on whether the state flag of a piddle |
893
|
|
|
|
|
|
|
# is set/change this state |
894
|
|
|
|
|
|
|
# |
895
|
|
|
|
|
|
|
# $PDLSTATEISBAD(a) -> ($PDL(a)->state & PDL_BADVAL) > 0 |
896
|
|
|
|
|
|
|
# $PDLSTATEISGOOD(a) -> ($PDL(a)->state & PDL_BADVAL) == 0 |
897
|
|
|
|
|
|
|
# |
898
|
|
|
|
|
|
|
# $PDLSTATESETBAD(a) -> ($PDL(a)->state |= PDL_BADVAL) |
899
|
|
|
|
|
|
|
# $PDLSTATESETGOOD(a) -> ($PDL(a)->state &= ~PDL_BADVAL) |
900
|
|
|
|
|
|
|
# |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
package PDL::PP::PDLStateBadAccess; |
903
|
|
|
|
|
|
|
use Carp; |
904
|
|
|
|
|
|
|
our @CARP_NOT; |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
sub new { |
907
|
|
|
|
|
|
|
my ( $type, $op, $val, $pdl_name, $parent ) = @_; |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
# $op is one of: IS SET |
910
|
|
|
|
|
|
|
# $val is one of: GOOD BAD |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
# trying to avoid auto creation of hash elements |
913
|
|
|
|
|
|
|
my $check = $parent->{ParObjs}; |
914
|
|
|
|
|
|
|
die "\nIt looks like you have tried a \$PDLSTATE${op}${val}() macro on an\n" . |
915
|
|
|
|
|
|
|
" unknown piddle <$pdl_name>\n" |
916
|
|
|
|
|
|
|
unless exists($check->{$pdl_name}) and defined($check->{$pdl_name}); |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
bless [$op, $val, $pdl_name], $type; |
919
|
|
|
|
|
|
|
} |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
our %ops = ( |
922
|
|
|
|
|
|
|
IS => { GOOD => '== 0', BAD => '> 0' }, |
923
|
|
|
|
|
|
|
SET => { GOOD => '&= ~', BAD => '|= ' }, |
924
|
|
|
|
|
|
|
); |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
sub get_str { |
927
|
|
|
|
|
|
|
my($this,$parent,$context) = @_; |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
my $op = $this->[0]; |
930
|
|
|
|
|
|
|
my $val = $this->[1]; |
931
|
|
|
|
|
|
|
my $name = $this->[2]; |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
print "PDL::PP::PDLStateBadAccess sent [$op] [$val] [$name]\n" if $::PP_VERBOSE; |
934
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
my $opcode = $ops{$op}{$val}; |
936
|
|
|
|
|
|
|
my $type = $op . $val; |
937
|
|
|
|
|
|
|
die "ERROR: unknown check <$type> sent to PDL::PP::PDLStateBadAccess\n" |
938
|
|
|
|
|
|
|
unless defined $opcode; |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
my $obj = $parent->{ParObjs}{$name}; |
941
|
|
|
|
|
|
|
die "\nERROR: ParObjs does not seem to exist for <$name> = problem in PDL::PP::PDLStateBadAccess\n" |
942
|
|
|
|
|
|
|
unless defined $obj; |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
my $state = $obj->do_pdlaccess() . "->state"; |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
my $str; |
947
|
|
|
|
|
|
|
if ( $op eq 'IS' ) { |
948
|
|
|
|
|
|
|
$str = "($state & PDL_BADVAL) $opcode"; |
949
|
|
|
|
|
|
|
} elsif ( $op eq 'SET' ) { |
950
|
|
|
|
|
|
|
$str = "$state ${opcode}PDL_BADVAL"; |
951
|
|
|
|
|
|
|
} |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
print "DBG: [$str]\n" if $::PP_VERBOSE; |
954
|
|
|
|
|
|
|
return $str; |
955
|
|
|
|
|
|
|
} |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
########################### |
959
|
|
|
|
|
|
|
# |
960
|
|
|
|
|
|
|
# Encapsulate a Pointeraccess |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
package PDL::PP::PointerAccess; |
963
|
|
|
|
|
|
|
use Carp; |
964
|
|
|
|
|
|
|
our @CARP_NOT; |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
967
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
969
|
|
|
|
|
|
|
croak ("can't access undefined pdl ".$this->[0]) |
970
|
|
|
|
|
|
|
unless defined($parent->{ParObjs}{$this->[0]}); |
971
|
|
|
|
|
|
|
# $parent->{ParObjs}{$this->[0]}->{FlagPaccess} = 1; |
972
|
|
|
|
|
|
|
$parent->{ParObjs}{$this->[0]}->{FlagPhys} = 1; |
973
|
|
|
|
|
|
|
$parent->{ParObjs}{$this->[0]}->do_pointeraccess(); |
974
|
|
|
|
|
|
|
} |
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
########################### |
978
|
|
|
|
|
|
|
# |
979
|
|
|
|
|
|
|
# Encapsulate a PhysPointeraccess |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
package PDL::PP::PhysPointerAccess; |
982
|
|
|
|
|
|
|
use Carp; |
983
|
|
|
|
|
|
|
our @CARP_NOT; |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
988
|
|
|
|
|
|
|
$parent->{ParObjs}{$this->[0]}->do_physpointeraccess() |
989
|
|
|
|
|
|
|
if defined($parent->{ParObjs}{$this->[0]}); |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
########################### |
993
|
|
|
|
|
|
|
# |
994
|
|
|
|
|
|
|
# Encapsulate a PDLaccess |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
package PDL::PP::PdlAccess; |
997
|
|
|
|
|
|
|
use Carp; |
998
|
|
|
|
|
|
|
our @CARP_NOT; |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
1003
|
|
|
|
|
|
|
croak ("can't access undefined pdl ".$this->[0]) |
1004
|
|
|
|
|
|
|
unless defined($parent->{ParObjs}{$this->[0]}); |
1005
|
|
|
|
|
|
|
$parent->{ParObjs}{$this->[0]}->do_pdlaccess(); |
1006
|
|
|
|
|
|
|
} |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
########################### |
1009
|
|
|
|
|
|
|
# |
1010
|
|
|
|
|
|
|
# Encapsulate a macroaccess |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
package PDL::PP::MacroAccess; |
1013
|
|
|
|
|
|
|
use Carp; |
1014
|
|
|
|
|
|
|
use PDL::Types ':All'; |
1015
|
|
|
|
|
|
|
my $types = join '',ppdefs; |
1016
|
|
|
|
|
|
|
our @CARP_NOT; |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
sub new { my($type,$pdl,$inds,$gentypes,$name) = @_; |
1019
|
|
|
|
|
|
|
$pdl =~ /^\s*T([A-Z]+)\s*$/ or confess("Macroaccess wrong: $pdl\n"); |
1020
|
|
|
|
|
|
|
my @ilst = split '',$1; |
1021
|
|
|
|
|
|
|
for my $gt (@$gentypes) { |
1022
|
|
|
|
|
|
|
warn "$name has no Macro for generic type $gt (has $pdl)\n" |
1023
|
|
|
|
|
|
|
unless grep {$gt eq $_} @ilst } |
1024
|
|
|
|
|
|
|
for my $mtype (@ilst) { |
1025
|
|
|
|
|
|
|
warn "Macro for unsupported generic type identifier $mtype". |
1026
|
|
|
|
|
|
|
" (probably harmless)\n" |
1027
|
|
|
|
|
|
|
unless grep {$mtype eq $_} @$gentypes; |
1028
|
|
|
|
|
|
|
} |
1029
|
|
|
|
|
|
|
return bless [$pdl,$inds,$name], |
1030
|
|
|
|
|
|
|
$type; } |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
1033
|
|
|
|
|
|
|
my ($pdl,$inds,$name) = @{$this}; |
1034
|
|
|
|
|
|
|
$pdl =~ /^\s*T([A-Z]+)\s*$/ |
1035
|
|
|
|
|
|
|
or confess("Macroaccess wrong in $name (allowed types $types): was '$pdl'\n"); |
1036
|
|
|
|
|
|
|
my @lst = split ',',$inds; |
1037
|
|
|
|
|
|
|
my @ilst = split '',$1; |
1038
|
|
|
|
|
|
|
if($#lst != $#ilst) {confess("Macroaccess: different nos of args $pdl $inds\n");} |
1039
|
|
|
|
|
|
|
croak "generic type access outside a generic loop in $name" |
1040
|
|
|
|
|
|
|
unless defined $parent->{Gencurtype}->[-1]; |
1041
|
|
|
|
|
|
|
my $type = mapfld $parent->{Gencurtype}->[-1], 'ctype' => 'ppsym'; |
1042
|
|
|
|
|
|
|
# print "Type access: $type\n"; |
1043
|
|
|
|
|
|
|
croak "unknown Type in $name (generic type currently $parent->{Gencurtype}->[-1]" |
1044
|
|
|
|
|
|
|
unless defined $type; |
1045
|
|
|
|
|
|
|
for (0..$#lst) { |
1046
|
|
|
|
|
|
|
return "$lst[$_]" if $ilst[$_] =~ /$type/; |
1047
|
|
|
|
|
|
|
} |
1048
|
|
|
|
|
|
|
} |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
########################### |
1052
|
|
|
|
|
|
|
# |
1053
|
|
|
|
|
|
|
# Encapsulate a SizeAccess |
1054
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
package PDL::PP::SizeAccess; |
1056
|
|
|
|
|
|
|
use Carp; |
1057
|
|
|
|
|
|
|
our @CARP_NOT; |
1058
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
1062
|
|
|
|
|
|
|
croak "can't get SIZE of undefined dimension $this->[0]" |
1063
|
|
|
|
|
|
|
unless defined($parent->{IndObjs}{$this->[0]}); |
1064
|
|
|
|
|
|
|
$parent->{IndObjs}{$this->[0]}->get_size(); |
1065
|
|
|
|
|
|
|
} |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
########################### |
1068
|
|
|
|
|
|
|
# |
1069
|
|
|
|
|
|
|
# Encapsulate a ReSizeAccess |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
package PDL::PP::ReSizeAccess; |
1072
|
|
|
|
|
|
|
use Carp; |
1073
|
|
|
|
|
|
|
our @CARP_NOT; |
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
1078
|
|
|
|
|
|
|
$this->[0] =~ /^([^,]+),([^,]+)$/ or |
1079
|
|
|
|
|
|
|
croak "Can't interpret resize str $this->[0]"; |
1080
|
|
|
|
|
|
|
croak "can't RESIZE undefined dimension $1" |
1081
|
|
|
|
|
|
|
unless defined($parent->{IndObjs}{$1}); |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
my $s = $parent->{IndObjs}{$1}->get_size(); |
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
# XXX NOTE: All piddles must be output piddles, there must not be |
1086
|
|
|
|
|
|
|
# a loop over this var (at all!) etc. Should check for these, |
1087
|
|
|
|
|
|
|
# this is why not yet documented. |
1088
|
|
|
|
|
|
|
# FURTHER NOTE: RESIZE DOESN'T COPY DATA PROPERLY! |
1089
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
my($ord,$pdls) = $parent->get_pdls(); |
1091
|
|
|
|
|
|
|
my @p; |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
for(@$ord) { |
1094
|
|
|
|
|
|
|
push @p, $_ |
1095
|
|
|
|
|
|
|
if $pdls->{$_}->has_dim($1); |
1096
|
|
|
|
|
|
|
} |
1097
|
|
|
|
|
|
|
print "RESIZEACC: $1 $2, (",(join ',',@p),")\n"; |
1098
|
|
|
|
|
|
|
warn "RESIZE USED: DO YOU KNOW WHAT YOU ARE DOING???\n"; |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
return "$s = $2; ".(join '',map {$pdls->{$_}->do_resize($1,$2)} @p); |
1101
|
|
|
|
|
|
|
} |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
########################### |
1105
|
|
|
|
|
|
|
# |
1106
|
|
|
|
|
|
|
# Encapsulate a GentypeAccess |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
package PDL::PP::GentypeAccess; |
1109
|
|
|
|
|
|
|
use Carp; |
1110
|
|
|
|
|
|
|
our @CARP_NOT; |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
sub get_str {my($this,$parent,$context) = @_; |
1115
|
|
|
|
|
|
|
croak "generic type access outside a generic loop" |
1116
|
|
|
|
|
|
|
unless defined $parent->{Gencurtype}->[-1]; |
1117
|
|
|
|
|
|
|
my $type = $parent->{Gencurtype}->[-1]; |
1118
|
|
|
|
|
|
|
if ($this->[0]) { |
1119
|
|
|
|
|
|
|
croak "not a defined name" |
1120
|
|
|
|
|
|
|
unless defined($parent->{ParObjs}{$this->[0]}); |
1121
|
|
|
|
|
|
|
$type = $parent->{ParObjs}{$this->[0]}->ctype($type); |
1122
|
|
|
|
|
|
|
} |
1123
|
|
|
|
|
|
|
return $type; |
1124
|
|
|
|
|
|
|
} |
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
######################## |
1127
|
|
|
|
|
|
|
# |
1128
|
|
|
|
|
|
|
# Type coercion |
1129
|
|
|
|
|
|
|
# |
1130
|
|
|
|
|
|
|
# Now, if TYPES:F given and double arguments, will coerce. |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
package PDL::PP::TypeConv; |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
# make the typetable from info in PDL::Types |
1135
|
|
|
|
|
|
|
use PDL::Types ':All'; |
1136
|
|
|
|
|
|
|
my @typetable = map {[$typehash{$_}->{ppsym}, |
1137
|
|
|
|
|
|
|
$typehash{$_}->{ctype}, |
1138
|
|
|
|
|
|
|
$typehash{$_}->{numval}, |
1139
|
|
|
|
|
|
|
]} typesrtkeys; |
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
sub print_xscoerce { my($this) = @_; |
1142
|
|
|
|
|
|
|
$this->printxs("\t__priv->datatype=PDL_B;\n"); |
1143
|
|
|
|
|
|
|
# First, go through all the types, selecting the most general. |
1144
|
|
|
|
|
|
|
for(@{$this->{PdlOrder}}) { |
1145
|
|
|
|
|
|
|
$this->printxs($this->{Pdls}{$_}->get_xsdatatypetest()); |
1146
|
|
|
|
|
|
|
} |
1147
|
|
|
|
|
|
|
# See which types we are allowed to use. |
1148
|
|
|
|
|
|
|
$this->printxs("\tif(0) {}\n"); |
1149
|
|
|
|
|
|
|
for(@{$this->get_generictypes()}) { |
1150
|
|
|
|
|
|
|
$this->printxs("\telse if(__priv->datatype <= $_->[2]) __priv->datatype = $_->[2];\n"); |
1151
|
|
|
|
|
|
|
} |
1152
|
|
|
|
|
|
|
$this->{Types} =~ /F/ and ( |
1153
|
|
|
|
|
|
|
$this->printxs("\telse if(__priv->datatype == PDL_D) {__priv->datatype = PDL_F; PDL_COMMENT(\"Cast double to float\")}\n")); |
1154
|
|
|
|
|
|
|
$this->printxs(qq[\telse {croak("Too high type \%d given!\\n",__priv->datatype);}]); |
1155
|
|
|
|
|
|
|
# Then, coerce everything to this type. |
1156
|
|
|
|
|
|
|
for(@{$this->{PdlOrder}}) { |
1157
|
|
|
|
|
|
|
$this->printxs($this->{Pdls}{$_}->get_xscoerce()); |
1158
|
|
|
|
|
|
|
} |
1159
|
|
|
|
|
|
|
} |
1160
|
|
|
|
|
|
|
# XXX Should use PDL::Core::Dev; |
1161
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
no strict 'vars'; |
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
# STATIC! |
1165
|
|
|
|
|
|
|
sub PDL::PP::get_generictyperecs { my($types) = @_; |
1166
|
|
|
|
|
|
|
my $foo; |
1167
|
|
|
|
|
|
|
return [map {$foo = $_; |
1168
|
|
|
|
|
|
|
( grep {/$foo->[0]/} (@$types) ) ? |
1169
|
|
|
|
|
|
|
[mapfld($_->[0],'ppsym'=>'sym'),$_->[1],$_->[2],$_->[0]] |
1170
|
|
|
|
|
|
|
: () |
1171
|
|
|
|
|
|
|
} |
1172
|
|
|
|
|
|
|
@typetable]; |
1173
|
|
|
|
|
|
|
} |
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
sub xxx_get_generictypes { my($this) = @_; |
1176
|
|
|
|
|
|
|
return [map { |
1177
|
|
|
|
|
|
|
$this->{Types} =~ /$_->[0]/ ? [mapfld($_->[0],'ppsym'=>'sym'),$_->[1],$_->[2],$_->[0]] : () |
1178
|
|
|
|
|
|
|
} |
1179
|
|
|
|
|
|
|
@typetable]; |
1180
|
|
|
|
|
|
|
} |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
package PDL::PP::Code; |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
# my ( $threadloops, $coderef, $sizeprivs ) = $this->separate_code( $code ); |
1186
|
|
|
|
|
|
|
# |
1187
|
|
|
|
|
|
|
# umm, can't call classes defined later on in code ... |
1188
|
|
|
|
|
|
|
# hence moved to end of file |
1189
|
|
|
|
|
|
|
# (rather ugly...) |
1190
|
|
|
|
|
|
|
# |
1191
|
|
|
|
|
|
|
# XXX The above statement is almost certainly false. This module is parsed |
1192
|
|
|
|
|
|
|
# before separate_code is ever called, so all of the class definitions |
1193
|
|
|
|
|
|
|
# should exist. -- David Mertens, Dec 2 2011 |
1194
|
|
|
|
|
|
|
# |
1195
|
|
|
|
|
|
|
# separates the code into an array of C fragments (strings), |
1196
|
|
|
|
|
|
|
# variable references (strings starting with $) and |
1197
|
|
|
|
|
|
|
# loops (array references, 1. item = variable. |
1198
|
|
|
|
|
|
|
# |
1199
|
|
|
|
|
|
|
sub separate_code { |
1200
|
|
|
|
|
|
|
## $DB::single=1; |
1201
|
|
|
|
|
|
|
my ( $this, $code ) = @_; |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
# First check for standard code errors: |
1204
|
|
|
|
|
|
|
catch_code_errors($code); |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
my $coderef = new PDL::PP::Block; |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
my @stack = ($coderef); |
1209
|
|
|
|
|
|
|
my $threadloops = 0; |
1210
|
|
|
|
|
|
|
my $sizeprivs = {}; |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
local $_ = $code; |
1213
|
|
|
|
|
|
|
## print "Code to parse = [$_]\n" if $::PP_VERBOSE; |
1214
|
|
|
|
|
|
|
while($_) { |
1215
|
|
|
|
|
|
|
# Parse next statement |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
# I'm not convinced that having the checks twice is a good thing, |
1218
|
|
|
|
|
|
|
# since it makes it easy (for me at least) to forget to update one |
1219
|
|
|
|
|
|
|
# of them |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
s/^(.*?) # First, some noise is allowed. This may be bad. |
1222
|
|
|
|
|
|
|
( \$(ISBAD|ISGOOD|SETBAD)\s*\(\s*\$?[a-zA-Z_]\w*\s*\([^)]*\)\s*\) # $ISBAD($a(..)), ditto for ISGOOD and SETBAD |
1223
|
|
|
|
|
|
|
|\$PP(ISBAD|ISGOOD|SETBAD)\s*\(\s*[a-zA-Z_]\w*\s*,\s*[^)]*\s*\) # $PPISBAD(CHILD,[1]) etc |
1224
|
|
|
|
|
|
|
### |\$STATE(IS|SET)(BAD|GOOD)\s*\(\s*[^)]*\s*\) # $STATEISBAD(a) etc |
1225
|
|
|
|
|
|
|
|\$PDLSTATE(IS|SET)(BAD|GOOD)\s*\(\s*[^)]*\s*\) # $PDLSTATEISBAD(a) etc |
1226
|
|
|
|
|
|
|
|\$[a-zA-Z_]\w*\s*\([^)]*\) # $a(...): access |
1227
|
|
|
|
|
|
|
|\bloop\s*\([^)]+\)\s*%\{ # loop(..) %{ |
1228
|
|
|
|
|
|
|
|\btypes\s*\([^)]+\)\s*%\{ # types(..) %{ |
1229
|
|
|
|
|
|
|
|\bthreadloop\s*%\{ # threadloop %{ |
1230
|
|
|
|
|
|
|
|%} # %} |
1231
|
|
|
|
|
|
|
|$)//xs |
1232
|
|
|
|
|
|
|
or confess("Invalid program $_"); |
1233
|
|
|
|
|
|
|
my $control = $2; |
1234
|
|
|
|
|
|
|
# Store the user code. |
1235
|
|
|
|
|
|
|
# Some day we shall parse everything. |
1236
|
|
|
|
|
|
|
push @{$stack[-1]},$1; |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
if ( $control =~ /^\$STATE/ ) { print "\nDBG: - got [$control]\n\n"; } |
1239
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
# Then, our control. |
1241
|
|
|
|
|
|
|
if($control) { |
1242
|
|
|
|
|
|
|
if($control =~ /^loop\s*\(([^)]+)\)\s*%\{/) { |
1243
|
|
|
|
|
|
|
my $ob = new PDL::PP::Loop([split ',',$1], |
1244
|
|
|
|
|
|
|
$sizeprivs,$this); |
1245
|
|
|
|
|
|
|
print "SIZEPRIVSXX: $sizeprivs,",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
1246
|
|
|
|
|
|
|
push @{$stack[-1]},$ob; |
1247
|
|
|
|
|
|
|
push @stack,$ob; |
1248
|
|
|
|
|
|
|
} elsif($control =~ /^types\s*\(([^)]+)\)\s*%\{/) { |
1249
|
|
|
|
|
|
|
my $ob = new PDL::PP::Types($1,$this); |
1250
|
|
|
|
|
|
|
push @{$stack[-1]},$ob; |
1251
|
|
|
|
|
|
|
push @stack,$ob; |
1252
|
|
|
|
|
|
|
} elsif($control =~ /^threadloop\s*%\{/) { |
1253
|
|
|
|
|
|
|
my $ob = new PDL::PP::ThreadLoop(); |
1254
|
|
|
|
|
|
|
push @{$stack[-1]},$ob; |
1255
|
|
|
|
|
|
|
push @stack,$ob; |
1256
|
|
|
|
|
|
|
$threadloops ++; |
1257
|
|
|
|
|
|
|
} elsif($control =~ /^\$PP(ISBAD|ISGOOD|SETBAD)\s*\(\s*([a-zA-Z_]\w*)\s*,\s*([^)]*)\s*\)/) { |
1258
|
|
|
|
|
|
|
push @{$stack[-1]},new PDL::PP::PPBadAccess($1,$2,$3,$this); |
1259
|
|
|
|
|
|
|
} elsif($control =~ /^\$(ISBAD|ISGOOD|SETBAD)VAR\s*\(\s*([^)]*)\s*,\s*([^)]*)\s*\)/) { |
1260
|
|
|
|
|
|
|
push @{$stack[-1]},new PDL::PP::BadVarAccess($1,$2,$3,$this); |
1261
|
|
|
|
|
|
|
} elsif($control =~ /^\$(ISBAD|ISGOOD|SETBAD)\s*\(\s*\$?([a-zA-Z_]\w*)\s*\(([^)]*)\)\s*\)/) { |
1262
|
|
|
|
|
|
|
push @{$stack[-1]},new PDL::PP::BadAccess($1,$2,$3,$this); |
1263
|
|
|
|
|
|
|
# } elsif($control =~ /^\$STATE(IS|SET)(BAD|GOOD)\s*\(\s*([^)]*)\s*\)/) { |
1264
|
|
|
|
|
|
|
# push @{$stack[-1]},new PDL::PP::StateBadAccess($1,$2,$3,$this); |
1265
|
|
|
|
|
|
|
} elsif($control =~ /^\$PDLSTATE(IS|SET)(BAD|GOOD)\s*\(\s*([^)]*)\s*\)/) { |
1266
|
|
|
|
|
|
|
push @{$stack[-1]},new PDL::PP::PDLStateBadAccess($1,$2,$3,$this); |
1267
|
|
|
|
|
|
|
} elsif($control =~ /^\$[a-zA-Z_]\w*\s*\([^)]*\)/) { |
1268
|
|
|
|
|
|
|
push @{$stack[-1]},new PDL::PP::Access($control,$this); |
1269
|
|
|
|
|
|
|
} elsif($control =~ /^%}/) { |
1270
|
|
|
|
|
|
|
pop @stack; |
1271
|
|
|
|
|
|
|
} else { |
1272
|
|
|
|
|
|
|
confess("Invalid control: $control\n"); |
1273
|
|
|
|
|
|
|
} |
1274
|
|
|
|
|
|
|
} else { |
1275
|
|
|
|
|
|
|
print("No \$2!\n") if $::PP_VERBOSE; |
1276
|
|
|
|
|
|
|
} |
1277
|
|
|
|
|
|
|
} # while: $_ |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
return ( $threadloops, $coderef, $sizeprivs ); |
1280
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
} # sub: separate_code() |
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
# This is essentially a collection of regexes that look for standard code |
1284
|
|
|
|
|
|
|
# errors and croaks with an explanation if they are found. |
1285
|
|
|
|
|
|
|
sub catch_code_errors { |
1286
|
|
|
|
|
|
|
my $code_string = shift; |
1287
|
|
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
# Look for constructs like |
1289
|
|
|
|
|
|
|
# loop %{ |
1290
|
|
|
|
|
|
|
# which is invalid - you need to specify the dimension over which it |
1291
|
|
|
|
|
|
|
# should loop |
1292
|
|
|
|
|
|
|
report_error('Expected dimension name after "loop" and before "%{"', $1) |
1293
|
|
|
|
|
|
|
if $code_string =~ /(.*\bloop\s*%\{)/s; |
1294
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
} |
1296
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
# Report an error as precisely as possible. If they have #line directives |
1298
|
|
|
|
|
|
|
# in the code string, use that in the reporting; otherwise, use standard |
1299
|
|
|
|
|
|
|
# Carp mechanisms |
1300
|
|
|
|
|
|
|
my $line_re = qr/#\s*line\s+(\d+)\s+"([^"]*)"/; |
1301
|
|
|
|
|
|
|
sub report_error { |
1302
|
|
|
|
|
|
|
my ($message, $code) = @_; |
1303
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
# Just croak if they didn't supply a #line directive: |
1305
|
|
|
|
|
|
|
croak($message) if $code !~ $line_re; |
1306
|
|
|
|
|
|
|
|
1307
|
|
|
|
|
|
|
# Find the line at which the error occurred: |
1308
|
|
|
|
|
|
|
my $line = 0; |
1309
|
|
|
|
|
|
|
my $filename; |
1310
|
|
|
|
|
|
|
LINE: foreach (split /\n/, $code) { |
1311
|
|
|
|
|
|
|
$line++; |
1312
|
|
|
|
|
|
|
if (/$line_re/) { |
1313
|
|
|
|
|
|
|
$line = $1; |
1314
|
|
|
|
|
|
|
$filename = $2; |
1315
|
|
|
|
|
|
|
} |
1316
|
|
|
|
|
|
|
} |
1317
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
die "$message at $filename line $line\n"; |
1319
|
|
|
|
|
|
|
} |
1320
|
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
# return true |
1322
|
|
|
|
|
|
|
1; |