30
30
import static com .oracle .graal .python .nodes .SpecialMethodNames .__REPR__ ;
31
31
import static com .oracle .graal .python .runtime .exception .PythonErrorType .StopIteration ;
32
32
import static com .oracle .graal .python .runtime .exception .PythonErrorType .TypeError ;
33
+ import static com .oracle .graal .python .runtime .exception .PythonErrorType .ValueError ;
33
34
34
35
import java .util .List ;
35
36
@@ -113,13 +114,16 @@ private static Object[] prepareArguments(PGenerator self) {
113
114
return arguments ;
114
115
}
115
116
116
- private static Object resumeGenerator (PGenerator self ) {
117
+ private static Object resumeGenerator (PGenerator self , Object sendValue ) {
117
118
try {
119
+ self .setRunning (true );
120
+ PArguments .setSpecialArgument (self .getArguments (), sendValue );
118
121
return self .getCurrentCallTarget ().call (prepareArguments (self ));
119
122
} catch (PException e ) {
120
123
self .markAsFinished ();
121
124
throw e ;
122
125
} finally {
126
+ self .setRunning (false );
123
127
self .setNextCallTarget ();
124
128
PArguments .setSpecialArgument (self .getArguments (), null );
125
129
}
@@ -159,32 +163,46 @@ protected static boolean sameCallTarget(RootCallTarget target1, CallTarget targe
159
163
160
164
@ Specialization (guards = "sameCallTarget(self.getCurrentCallTarget(), call.getCallTarget())" , limit = "getCallSiteInlineCacheMaxDepth()" )
161
165
public Object nextCached (VirtualFrame frame , PGenerator self ,
162
- @ Cached ("createDirectCall(self.getCurrentCallTarget())" ) CallTargetInvokeNode call ) {
166
+ @ Cached ("createDirectCall(self.getCurrentCallTarget())" ) CallTargetInvokeNode call ,
167
+ @ Cached BranchProfile alreadyRunning ) {
163
168
if (self .isFinished ()) {
164
169
throw raise (StopIteration );
165
170
}
171
+ if (self .isRunning ()) {
172
+ alreadyRunning .enter ();
173
+ throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
174
+ }
166
175
try {
176
+ self .setRunning (true );
167
177
return call .execute (frame , null , null , prepareArguments (self ));
168
178
} catch (PException e ) {
169
179
self .markAsFinished ();
170
180
throw e ;
171
181
} finally {
182
+ self .setRunning (false );
172
183
self .setNextCallTarget ();
173
184
}
174
185
}
175
186
176
187
@ Specialization (replaces = "nextCached" )
177
188
public Object next (VirtualFrame frame , PGenerator self ,
178
- @ Cached ("createIndirectCall()" ) GenericInvokeNode call ) {
189
+ @ Cached ("createIndirectCall()" ) GenericInvokeNode call ,
190
+ @ Cached BranchProfile alreadyRunning ) {
179
191
if (self .isFinished ()) {
180
192
throw raise (StopIteration );
181
193
}
194
+ if (self .isRunning ()) {
195
+ alreadyRunning .enter ();
196
+ throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
197
+ }
182
198
try {
199
+ self .setRunning (true );
183
200
return call .execute (frame , self .getCurrentCallTarget (), prepareArguments (self ));
184
201
} catch (PException e ) {
185
202
self .markAsFinished ();
186
203
throw e ;
187
204
} finally {
205
+ self .setRunning (false );
188
206
self .setNextCallTarget ();
189
207
}
190
208
}
@@ -195,9 +213,13 @@ public Object next(VirtualFrame frame, PGenerator self,
195
213
public abstract static class SendNode extends PythonBuiltinNode {
196
214
197
215
@ Specialization
198
- public Object send (PGenerator self , Object value ) {
199
- PArguments .setSpecialArgument (self .getArguments (), value );
200
- return resumeGenerator (self );
216
+ public Object send (PGenerator self , Object value ,
217
+ @ Cached BranchProfile alreadyRunning ) {
218
+ if (self .isRunning ()) {
219
+ alreadyRunning .enter ();
220
+ throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
221
+ }
222
+ return resumeGenerator (self , value );
201
223
}
202
224
}
203
225
@@ -308,14 +330,24 @@ private void checkExceptionClass(LazyPythonClass type) {
308
330
309
331
@ Specialization
310
332
Object sendThrow (VirtualFrame frame , PGenerator self , Object typ , Object val , @ SuppressWarnings ("unused" ) PNone tb ,
311
- @ Cached PrepareExceptionNode prepareExceptionNode ) {
333
+ @ Cached PrepareExceptionNode prepareExceptionNode ,
334
+ @ Cached BranchProfile alreadyRunning ) {
335
+ if (self .isRunning ()) {
336
+ alreadyRunning .enter ();
337
+ throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
338
+ }
312
339
PBaseException instance = prepareExceptionNode .execute (frame , typ , val );
313
340
return doThrow (self , instance );
314
341
}
315
342
316
343
@ Specialization
317
344
Object sendThrow (VirtualFrame frame , PGenerator self , Object typ , Object val , PTraceback tb ,
318
- @ Cached PrepareExceptionNode prepareExceptionNode ) {
345
+ @ Cached PrepareExceptionNode prepareExceptionNode ,
346
+ @ Cached BranchProfile alreadyRunning ) {
347
+ if (self .isRunning ()) {
348
+ alreadyRunning .enter ();
349
+ throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
350
+ }
319
351
PBaseException instance = prepareExceptionNode .execute (frame , typ , val );
320
352
instance .setTraceback (tb );
321
353
return doThrow (self , instance );
@@ -328,8 +360,7 @@ private Object doThrow(PGenerator self, PBaseException instance) {
328
360
// Pass it to the generator where it will be thrown by the last yield, the location
329
361
// will be filled there
330
362
PException pException = PException .fromObject (instance , null );
331
- PArguments .setSpecialArgument (self .getArguments (), pException );
332
- return resumeGenerator (self );
363
+ return resumeGenerator (self , pException );
333
364
} else {
334
365
// Unstarted generator, we cannot pass the exception into the generator as there is
335
366
// nothing that would handle it.
@@ -373,7 +404,7 @@ private GetTracebackNode ensureGetTracebackNode() {
373
404
374
405
@ Builtin (name = "gi_code" , minNumOfPositionalArgs = 1 , isGetter = true )
375
406
@ GenerateNodeFactory
376
- public abstract static class GetCodeNode extends PythonBuiltinNode {
407
+ public abstract static class GetCodeNode extends PythonUnaryBuiltinNode {
377
408
@ Specialization
378
409
Object getCode (PGenerator self ,
379
410
@ Cached ("createBinaryProfile()" ) ConditionProfile hasCodeProfile ) {
@@ -386,6 +417,15 @@ Object getCode(PGenerator self,
386
417
}
387
418
}
388
419
420
+ @ Builtin (name = "gi_running" , minNumOfPositionalArgs = 1 , isGetter = true )
421
+ @ GenerateNodeFactory
422
+ public abstract static class GetRunningNode extends PythonUnaryBuiltinNode {
423
+ @ Specialization
424
+ static Object getRunning (PGenerator self ) {
425
+ return self .isRunning ();
426
+ }
427
+ }
428
+
389
429
@ Builtin (name = __REPR__ , minNumOfPositionalArgs = 1 )
390
430
@ GenerateNodeFactory
391
431
abstract static class ReprNode extends PythonUnaryBuiltinNode {
0 commit comments