35
35
import com .oracle .graal .python .nodes .PRaiseNode ;
36
36
import com .oracle .graal .python .nodes .builtins .TupleNodes ;
37
37
import com .oracle .graal .python .nodes .expression .ExpressionNode ;
38
+ import com .oracle .graal .python .nodes .frame .DestructuringAssignmentNodeGen .WriteSequenceStorageStarredNodeGen ;
38
39
import com .oracle .graal .python .nodes .object .IsBuiltinClassProfile ;
39
40
import com .oracle .graal .python .nodes .statement .StatementNode ;
40
41
import com .oracle .graal .python .runtime .PythonContext ;
46
47
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
47
48
import com .oracle .truffle .api .TruffleLanguage .ContextReference ;
48
49
import com .oracle .truffle .api .dsl .Cached ;
50
+ import com .oracle .truffle .api .dsl .Cached .Shared ;
49
51
import com .oracle .truffle .api .dsl .Specialization ;
50
52
import com .oracle .truffle .api .frame .VirtualFrame ;
51
53
import com .oracle .truffle .api .nodes .ExplodeLoop ;
54
+ import com .oracle .truffle .api .nodes .Node ;
52
55
53
56
public abstract class DestructuringAssignmentNode extends StatementNode implements WriteNode {
54
57
/* Lazily initialized helpers, also acting as branch profiles */
55
58
@ Child private PRaiseNode raiseNode ;
56
- @ Child private PythonObjectFactory factory ;
57
59
@ CompilationFinal private ContextReference <PythonContext > contextRef ;
58
60
59
61
/* Syntactic children */
@@ -102,7 +104,7 @@ protected static boolean isBuiltinTuple(Object object, IsBuiltinClassProfile pro
102
104
}
103
105
104
106
@ Specialization (guards = {"isBuiltinList(rhsVal, isBuiltinClass)" , "starredIndex < 0" })
105
- public void writeList (VirtualFrame frame , PList rhsVal ,
107
+ void writeList (VirtualFrame frame , PList rhsVal ,
106
108
@ Cached SequenceStorageNodes .LenNode lenNode ,
107
109
@ Cached SequenceStorageNodes .GetItemNode getItemNode ,
108
110
@ SuppressWarnings ("unused" ) @ Cached IsBuiltinClassProfile isBuiltinClass ) {
@@ -112,7 +114,7 @@ public void writeList(VirtualFrame frame, PList rhsVal,
112
114
}
113
115
114
116
@ Specialization (guards = {"isBuiltinTuple(rhsVal, isBuiltinClass)" , "starredIndex < 0" })
115
- public void writeTuple (VirtualFrame frame , PTuple rhsVal ,
117
+ void writeTuple (VirtualFrame frame , PTuple rhsVal ,
116
118
@ Cached SequenceStorageNodes .LenNode lenNode ,
117
119
@ Cached SequenceStorageNodes .GetItemNode getItemNode ,
118
120
@ SuppressWarnings ("unused" ) @ Cached IsBuiltinClassProfile isBuiltinClass ) {
@@ -137,51 +139,24 @@ private void writeSequenceStorage(VirtualFrame frame, SequenceStorage sequenceSt
137
139
}
138
140
}
139
141
140
- @ Specialization (guards = {"isBuiltinList(rhsVal, isBuiltinClass)" , "starredIndex >= 0" })
141
- public void writeListStarred (VirtualFrame frame , PList rhsVal ,
142
- @ Cached SequenceStorageNodes .LenNode lenNode ,
143
- @ Cached SequenceStorageNodes .GetItemNode getItemNode ,
142
+ @ Specialization (guards = {"isBuiltinList(rhsVal, isBuiltinClass)" , "starredIndex >= 0" }, limit = "1" )
143
+ void writeListStarred (VirtualFrame frame , PList rhsVal ,
144
+ @ Shared ("writeStarred" ) @ Cached WriteSequenceStorageStarredNode writeSequenceStorageStarredNode ,
144
145
@ SuppressWarnings ("unused" ) @ Cached IsBuiltinClassProfile isBuiltinClass ) {
145
146
SequenceStorage sequenceStorage = rhsVal .getSequenceStorage ();
146
- writeSequenceStorageStarred (frame , sequenceStorage , lenNode , getItemNode );
147
+ writeSequenceStorageStarredNode . execute (frame , sequenceStorage , slots , starredIndex );
147
148
performAssignments (frame );
148
149
}
149
150
150
- @ Specialization (guards = {"isBuiltinTuple(rhsVal, isBuiltinClass)" , "starredIndex >= 0" })
151
- public void writeTupleStarred (VirtualFrame frame , PTuple rhsVal ,
152
- @ Cached SequenceStorageNodes .LenNode lenNode ,
153
- @ Cached SequenceStorageNodes .GetItemNode getItemNode ,
151
+ @ Specialization (guards = {"isBuiltinTuple(rhsVal, isBuiltinClass)" , "starredIndex >= 0" }, limit = "1" )
152
+ void writeTupleStarred (VirtualFrame frame , PTuple rhsVal ,
153
+ @ Shared ("writeStarred" ) @ Cached WriteSequenceStorageStarredNode writeSequenceStorageStarredNode ,
154
154
@ SuppressWarnings ("unused" ) @ Cached IsBuiltinClassProfile isBuiltinClass ) {
155
155
SequenceStorage sequenceStorage = rhsVal .getSequenceStorage ();
156
- writeSequenceStorageStarred (frame , sequenceStorage , lenNode , getItemNode );
156
+ writeSequenceStorageStarredNode . execute (frame , sequenceStorage , slots , starredIndex );
157
157
performAssignments (frame );
158
158
}
159
159
160
- @ ExplodeLoop
161
- private void writeSequenceStorageStarred (VirtualFrame frame , SequenceStorage sequenceStorage , SequenceStorageNodes .LenNode lenNode , SequenceStorageNodes .GetItemNode getItemNode ) {
162
- int len = lenNode .execute (sequenceStorage );
163
- if (len < slots .length - 1 ) {
164
- throw ensureRaiseNode ().raise (ValueError , "not enough values to unpack (expected %d, got %d)" , slots .length , len );
165
- } else {
166
- for (int i = 0 ; i < starredIndex ; i ++) {
167
- Object value = getItemNode .execute (frame , sequenceStorage , i );
168
- slots [i ].doWrite (frame , value );
169
- }
170
- final int starredLength = len - (slots .length - 1 );
171
- Object [] array = new Object [starredLength ];
172
- CompilerAsserts .partialEvaluationConstant (starredLength );
173
- int pos = starredIndex ;
174
- for (int i = 0 ; i < starredLength ; i ++) {
175
- array [i ] = getItemNode .execute (frame , sequenceStorage , pos ++);
176
- }
177
- slots [starredIndex ].doWrite (frame , factory ().createList (array ));
178
- for (int i = starredIndex + 1 ; i < slots .length ; i ++) {
179
- Object value = getItemNode .execute (frame , sequenceStorage , pos ++);
180
- slots [i ].doWrite (frame , value );
181
- }
182
- }
183
- }
184
-
185
160
@ ExplodeLoop
186
161
private void performAssignments (VirtualFrame frame ) {
187
162
for (int i = 0 ; i < assignments .length ; i ++) {
@@ -190,28 +165,25 @@ private void performAssignments(VirtualFrame frame) {
190
165
}
191
166
192
167
@ Specialization (guards = {"!isBuiltinTuple(iterable, tupleProfile)" , "!isBuiltinList(iterable, listProfile)" , "starredIndex < 0" })
193
- public void writeIterable (VirtualFrame frame , Object iterable ,
168
+ void writeIterable (VirtualFrame frame , Object iterable ,
194
169
@ Cached TupleNodes .ConstructTupleNode constructTupleNode ,
195
170
@ Cached SequenceStorageNodes .LenNode lenNode ,
196
171
@ Cached SequenceStorageNodes .GetItemNode getItemNode ,
197
172
@ SuppressWarnings ("unused" ) @ Cached IsBuiltinClassProfile tupleProfile ,
198
173
@ SuppressWarnings ("unused" ) @ Cached IsBuiltinClassProfile listProfile ) {
199
174
PTuple rhsValue = constructTupleNode .execute (frame , iterable );
200
- SequenceStorage sequenceStorage = rhsValue .getSequenceStorage ();
201
- writeSequenceStorage (frame , sequenceStorage , lenNode , getItemNode );
175
+ writeSequenceStorage (frame , rhsValue .getSequenceStorage (), lenNode , getItemNode );
202
176
performAssignments (frame );
203
177
}
204
178
205
- @ Specialization (guards = {"!isBuiltinTuple(iterable, tupleProfile)" , "!isBuiltinList(iterable, listProfile)" , "starredIndex >= 0" })
206
- public void writeIterableStarred (VirtualFrame frame , Object iterable ,
179
+ @ Specialization (guards = {"!isBuiltinTuple(iterable, tupleProfile)" , "!isBuiltinList(iterable, listProfile)" , "starredIndex >= 0" }, limit = "1" )
180
+ void writeIterableStarred (VirtualFrame frame , Object iterable ,
207
181
@ Cached TupleNodes .ConstructTupleNode constructTupleNode ,
208
- @ Cached SequenceStorageNodes .LenNode lenNode ,
209
- @ Cached SequenceStorageNodes .GetItemNode getItemNode ,
182
+ @ Shared ("writeStarred" ) @ Cached WriteSequenceStorageStarredNode writeSequenceStorageStarredNode ,
210
183
@ SuppressWarnings ("unused" ) @ Cached IsBuiltinClassProfile tupleProfile ,
211
184
@ SuppressWarnings ("unused" ) @ Cached IsBuiltinClassProfile listProfile ) {
212
185
PTuple rhsValue = constructTupleNode .execute (frame , iterable );
213
- SequenceStorage sequenceStorage = rhsValue .getSequenceStorage ();
214
- writeSequenceStorageStarred (frame , sequenceStorage , lenNode , getItemNode );
186
+ writeSequenceStorageStarredNode .execute (frame , rhsValue .getSequenceStorage (), slots , starredIndex );
215
187
performAssignments (frame );
216
188
}
217
189
@@ -231,11 +203,109 @@ private PRaiseNode ensureRaiseNode() {
231
203
return raiseNode ;
232
204
}
233
205
234
- private PythonObjectFactory factory () {
235
- if (factory == null ) {
236
- CompilerDirectives .transferToInterpreterAndInvalidate ();
237
- factory = insert (PythonObjectFactory .create ());
206
+ /**
207
+ * This node performs assignments in form of
208
+ * {@code pre_0, pre_1, ..., pre_i, *starred, post_0, post_1, ..., post_k = sequenceObject}.
209
+ * Note that the parameters {@code slots} and {@code starredIndex} must be PE constant!
210
+ */
211
+ abstract static class WriteSequenceStorageStarredNode extends Node {
212
+
213
+ @ Child private PythonObjectFactory factory ;
214
+ @ Child private PRaiseNode raiseNode ;
215
+
216
+ abstract void execute (VirtualFrame frame , SequenceStorage storage , WriteNode [] slots , int starredIndex );
217
+
218
+ @ Specialization (guards = {"getLength(lenNode, storage) == cachedLength" }, limit = "1" )
219
+ void doExploded (VirtualFrame frame , SequenceStorage storage , WriteNode [] slots , int starredIndex ,
220
+ @ Shared ("getItemNode" ) @ Cached SequenceStorageNodes .GetItemNode getItemNode ,
221
+ @ Shared ("lenNode" ) @ Cached @ SuppressWarnings ("unused" ) SequenceStorageNodes .LenNode lenNode ,
222
+ @ Cached ("getLength(lenNode, storage)" ) int cachedLength ) {
223
+
224
+ CompilerAsserts .partialEvaluationConstant (slots );
225
+ CompilerAsserts .partialEvaluationConstant (starredIndex );
226
+ if (cachedLength < slots .length - 1 ) {
227
+ throw ensureRaiseNode ().raise (ValueError , "not enough values to unpack (expected %d, got %d)" , slots .length , cachedLength );
228
+ } else {
229
+ writeSlots (frame , storage , getItemNode , slots , starredIndex );
230
+ final int starredLength = cachedLength - (slots .length - 1 );
231
+ CompilerAsserts .partialEvaluationConstant (starredLength );
232
+ Object [] array = consumeStarredItems (frame , storage , starredLength , getItemNode , starredIndex );
233
+ assert starredLength == array .length ;
234
+ slots [starredIndex ].doWrite (frame , factory ().createList (array ));
235
+ performAssignmentsAfterStar (frame , storage , starredIndex + starredLength , getItemNode , slots , starredIndex );
236
+ }
237
+ }
238
+
239
+ @ Specialization (replaces = "doExploded" )
240
+ void doGeneric (VirtualFrame frame , SequenceStorage storage , WriteNode [] slots , int starredIndex ,
241
+ @ Shared ("getItemNode" ) @ Cached SequenceStorageNodes .GetItemNode getItemNode ,
242
+ @ Shared ("lenNode" ) @ Cached SequenceStorageNodes .LenNode lenNode ) {
243
+ CompilerAsserts .partialEvaluationConstant (slots );
244
+ CompilerAsserts .partialEvaluationConstant (starredIndex );
245
+ int len = lenNode .execute (storage );
246
+ if (len < slots .length - 1 ) {
247
+ throw ensureRaiseNode ().raise (ValueError , "not enough values to unpack (expected %d, got %d)" , slots .length , len );
248
+ } else {
249
+ writeSlots (frame , storage , getItemNode , slots , starredIndex );
250
+ final int starredLength = len - (slots .length - 1 );
251
+ Object [] array = new Object [starredLength ];
252
+ int pos = starredIndex ;
253
+ for (int i = 0 ; i < starredLength ; i ++) {
254
+ array [i ] = getItemNode .execute (frame , storage , pos ++);
255
+ }
256
+ slots [starredIndex ].doWrite (frame , factory ().createList (array ));
257
+ for (int i = starredIndex + 1 ; i < slots .length ; i ++) {
258
+ Object value = getItemNode .execute (frame , storage , pos ++);
259
+ slots [i ].doWrite (frame , value );
260
+ }
261
+ }
262
+ }
263
+
264
+ @ ExplodeLoop
265
+ private void writeSlots (VirtualFrame frame , SequenceStorage storage , SequenceStorageNodes .GetItemNode getItemNode , WriteNode [] slots , int starredIndex ) {
266
+ for (int i = 0 ; i < starredIndex ; i ++) {
267
+ Object value = getItemNode .execute (frame , storage , i );
268
+ slots [i ].doWrite (frame , value );
269
+ }
270
+ }
271
+
272
+ @ ExplodeLoop
273
+ private Object [] consumeStarredItems (VirtualFrame frame , SequenceStorage sequenceStorage , int starredLength , SequenceStorageNodes .GetItemNode getItemNode , int starredIndex ) {
274
+ Object [] array = new Object [starredLength ];
275
+ CompilerAsserts .partialEvaluationConstant (starredLength );
276
+ for (int i = 0 ; i < starredLength ; i ++) {
277
+ array [i ] = getItemNode .execute (frame , sequenceStorage , starredIndex + i );
278
+ }
279
+ return array ;
280
+ }
281
+
282
+ @ ExplodeLoop
283
+ private void performAssignmentsAfterStar (VirtualFrame frame , SequenceStorage sequenceStorage , int startPos , SequenceStorageNodes .GetItemNode getItemNode , WriteNode [] slots , int starredIndex ) {
284
+ for (int i = starredIndex + 1 , pos = startPos ; i < slots .length ; i ++, pos ++) {
285
+ Object value = getItemNode .execute (frame , sequenceStorage , pos );
286
+ slots [i ].doWrite (frame , value );
287
+ }
288
+ }
289
+
290
+ static int getLength (SequenceStorageNodes .LenNode lenNode , SequenceStorage storage ) {
291
+ return lenNode .execute (storage );
238
292
}
239
- return factory ;
293
+
294
+ private PythonObjectFactory factory () {
295
+ if (factory == null ) {
296
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
297
+ factory = insert (PythonObjectFactory .create ());
298
+ }
299
+ return factory ;
300
+ }
301
+
302
+ private PRaiseNode ensureRaiseNode () {
303
+ if (raiseNode == null ) {
304
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
305
+ raiseNode = insert (PRaiseNode .create ());
306
+ }
307
+ return raiseNode ;
308
+ }
309
+
240
310
}
241
311
}
0 commit comments