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