Commit 24041726 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #812 from undingen/generator_fixes

fix a few generator problems
parents e30f2897 e8192c99
...@@ -1142,6 +1142,9 @@ private: ...@@ -1142,6 +1142,9 @@ private:
push_back(makeExpr(new AST_LangPrimitive(AST_LangPrimitive::UNCACHE_EXC_INFO))); push_back(makeExpr(new AST_LangPrimitive(AST_LangPrimitive::UNCACHE_EXC_INFO)));
if (root_type != AST_TYPE::FunctionDef)
raiseExcHelper(SyntaxError, "'yield' outside function");
return makeLoad(node_name, node); return makeLoad(node_name, node);
} }
......
...@@ -120,6 +120,9 @@ Box* generatorIter(Box* s) { ...@@ -120,6 +120,9 @@ Box* generatorIter(Box* s) {
static void generatorSendInternal(BoxedGenerator* self, Box* v) { static void generatorSendInternal(BoxedGenerator* self, Box* v) {
STAT_TIMER(t0, "us_timer_generator_switching", 0); STAT_TIMER(t0, "us_timer_generator_switching", 0);
if (!self->returnContext && v != None)
raiseExcHelper(TypeError, "can't send non-None value to a just-started generator");
if (self->running) if (self->running)
raiseExcHelper(ValueError, "generator already executing"); raiseExcHelper(ValueError, "generator already executing");
...@@ -153,7 +156,6 @@ static void generatorSendInternal(BoxedGenerator* self, Box* v) { ...@@ -153,7 +156,6 @@ static void generatorSendInternal(BoxedGenerator* self, Box* v) {
// propagate exception to the caller // propagate exception to the caller
if (self->exception.type) { if (self->exception.type) {
assert(self->entryExited);
freeGeneratorStack(self); freeGeneratorStack(self);
// don't raise StopIteration exceptions because those are handled specially. // don't raise StopIteration exceptions because those are handled specially.
if (!self->exception.matches(StopIteration)) if (!self->exception.matches(StopIteration))
...@@ -205,19 +207,22 @@ Box* generatorThrow(Box* s, BoxedClass* exc_cls, Box* exc_val = nullptr, Box** a ...@@ -205,19 +207,22 @@ Box* generatorThrow(Box* s, BoxedClass* exc_cls, Box* exc_val = nullptr, Box** a
assert(s->cls == generator_cls); assert(s->cls == generator_cls);
BoxedGenerator* self = static_cast<BoxedGenerator*>(s); BoxedGenerator* self = static_cast<BoxedGenerator*>(s);
if (self->iterated_from__hasnext__) if (self->iterated_from__hasnext__ && !self->entryExited)
Py_FatalError(".throw called on generator last advanced with __hasnext__"); Py_FatalError(".throw called on generator last advanced with __hasnext__");
// don't overwrite self->exception if the generator already exited Box* exc_tb = args ? args[0] : nullptr;
// because it will contain the StopIteration exception to throw. if (exc_tb && exc_tb != None && !PyTraceBack_Check(exc_tb))
if (!self->entryExited) { raiseExcHelper(TypeError, "throw() third argument must be a traceback object");
Box* exc_tb = args ? nullptr : args[0]; if (!exc_val)
if (!exc_val) exc_val = None;
exc_val = None; if (!exc_tb)
if (!exc_tb) exc_tb = None;
exc_tb = None;
self->exception = excInfoForRaise(exc_cls, exc_val, exc_tb); ExcInfo exc_info = excInfoForRaise(exc_cls, exc_val, exc_tb);
} if (self->entryExited)
throw exc_info;
self->exception = exc_info;
return generatorSend(self, None); return generatorSend(self, None);
} }
...@@ -229,7 +234,15 @@ Box* generatorClose(Box* s) { ...@@ -229,7 +234,15 @@ Box* generatorClose(Box* s) {
if (self->entryExited) if (self->entryExited)
return None; return None;
return generatorThrow(self, GeneratorExit, nullptr, nullptr); try {
generatorThrow(self, GeneratorExit, nullptr, nullptr);
raiseExcHelper(RuntimeError, "generator ignored GeneratorExit");
} catch (ExcInfo e) {
if (e.matches(StopIteration) || e.matches(GeneratorExit))
return None;
throw e;
}
assert(0); // unreachable
} }
Box* generatorNext(Box* s) { Box* generatorNext(Box* s) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment