Skip to content

Commit 7953310

Browse files
committed
[GR-23272] Implement generator close method
PullRequest: graalpython/1038
2 parents 558d39f + bee67c8 commit 7953310

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/GeneratorBuiltins.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
*/
2626
package com.oracle.graal.python.builtins.objects.generator;
2727

28+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.GeneratorExit;
2829
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ITER__;
2930
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEXT__;
3031
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
32+
import static com.oracle.graal.python.runtime.exception.PythonErrorType.RuntimeError;
3133
import static com.oracle.graal.python.runtime.exception.PythonErrorType.StopIteration;
3234
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
3335
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
@@ -45,6 +47,7 @@
4547
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
4648
import com.oracle.graal.python.builtins.objects.frame.PFrame;
4749
import com.oracle.graal.python.builtins.objects.function.PArguments;
50+
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
4851
import com.oracle.graal.python.builtins.objects.traceback.GetTracebackNode;
4952
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
5053
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
@@ -61,6 +64,7 @@
6164
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
6265
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
6366
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
67+
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
6468
import com.oracle.graal.python.runtime.exception.PException;
6569
import com.oracle.graal.python.util.PythonUtils;
6670
import com.oracle.truffle.api.CallTarget;
@@ -76,6 +80,7 @@
7680
import com.oracle.truffle.api.dsl.Specialization;
7781
import com.oracle.truffle.api.frame.MaterializedFrame;
7882
import com.oracle.truffle.api.frame.VirtualFrame;
83+
import com.oracle.truffle.api.library.CachedLibrary;
7984
import com.oracle.truffle.api.nodes.Node;
8085
import com.oracle.truffle.api.profiles.BranchProfile;
8186
import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -402,6 +407,43 @@ private GetTracebackNode ensureGetTracebackNode() {
402407
}
403408
}
404409

410+
@Builtin(name = "close", minNumOfPositionalArgs = 1)
411+
@GenerateNodeFactory
412+
public abstract static class CloseNode extends PythonUnaryBuiltinNode {
413+
@Specialization
414+
Object close(PGenerator self,
415+
@CachedLibrary(limit = "3") PythonObjectLibrary lib,
416+
@Cached IsBuiltinClassProfile isGeneratorExit,
417+
@Cached IsBuiltinClassProfile isStopIteration,
418+
@Cached BranchProfile alreadyRunning) {
419+
if (self.isRunning()) {
420+
alreadyRunning.enter();
421+
throw raise(ValueError, ErrorMessages.GENERATOR_ALREADY_EXECUTING);
422+
}
423+
if (self.isStarted()) {
424+
PBaseException pythonException = factory().createBaseException(GeneratorExit);
425+
// Pass it to the generator where it will be thrown by the last yield, the location
426+
// will be filled there
427+
PException pException = PException.fromObject(pythonException, null);
428+
try {
429+
resumeGenerator(self, pException);
430+
} catch (PException pe) {
431+
if (isGeneratorExit.profileException(pe, GeneratorExit, lib) || isStopIteration.profileException(pe, StopIteration, lib)) {
432+
// This is the "success" path
433+
return PNone.NONE;
434+
}
435+
throw pe;
436+
} finally {
437+
self.markAsFinished();
438+
}
439+
throw raise(RuntimeError, ErrorMessages.GENERATOR_IGNORED_EXIT);
440+
} else {
441+
self.markAsFinished();
442+
return PNone.NONE;
443+
}
444+
}
445+
}
446+
405447
@Builtin(name = "gi_code", minNumOfPositionalArgs = 1, isGetter = true)
406448
@GenerateNodeFactory
407449
public abstract static class GetCodeNode extends PythonUnaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ public abstract class ErrorMessages {
215215
public static final String FUNC_CONSTRUCTION_NOT_SUPPORTED = "function construction not supported for (%p, %p, %p, %p, %p, %p)";
216216
public static final String FUNC_TAKES_AT_LEAST_D_ARGS = "function takes at least %d arguments (%d given)";
217217
public static final String FUNC_TAKES_EXACTLY_D_ARGS = "function takes exaclty %d arguments (%d given)";
218+
public static final String GENERATOR_IGNORED_EXIT = "generator ignored GeneratorExit";
218219
public static final String GENERATOR_RAISED_STOPITER = "generator raised StopIteration";
219220
public static final String GENERATOR_ALREADY_EXECUTING = "generator already executing";
220221
public static final String GETTING_THER_SOURCE_NOT_SUPPORTED_FOR_P = "getting the source is not supported for '%p'";

0 commit comments

Comments
 (0)