Author: Armin Rigo <ar...@tunes.org> Branch: py3.5-corowrapper Changeset: r87130:d4e91edb572f Date: 2016-09-16 11:42 +0200 http://bitbucket.org/pypy/pypy/changeset/d4e91edb572f/
Log: in-progress diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py --- a/pypy/interpreter/generator.py +++ b/pypy/interpreter/generator.py @@ -167,9 +167,10 @@ return self.throw(w_type, w_val, w_tb) def _get_yield_from(self): - # Probably a hack (but CPython has the same): + # Probably a hack (but CPython has the same, _PyGen_yf()): # If the current frame is stopped in a "yield from", # return the paused generator. + # XXX this is probably very bad for the JIT. Think again! if not self.frame: return None co_code = self.frame.pycode.co_code @@ -185,26 +186,29 @@ # Paused in a "yield from", pass the throw to the inner generator. return self._throw_delegate(space, w_yf, w_type, w_val, w_tb) else: - # Not paused in a "yield from", quit this generator + # Not paused in a "yield from", throw inside this generator return self._throw_here(space, w_type, w_val, w_tb) def _throw_delegate(self, space, w_yf, w_type, w_val, w_tb): - if space.is_w(w_type, space.w_GeneratorExit): + if space.exception_match(w_type, space.w_GeneratorExit): try: - w_close = space.getattr(w_yf, space.wrap("close")) - except OperationError as e: - if not e.match(space, space.w_AttributeError): - e.write_unraisable(space, "generator.close()") - else: self.running = True try: - space.call_function(w_close) - except OperationError as operr: - self.running = False - return self.send_ex(space.w_None, operr) + gen_close_iter(space, w_yf) finally: self.running = False + except OperationError as e: + return self.send_ex(space.w_None, e) return self._throw_here(space, w_type, w_val, w_tb) + # + if isinstance(w_yf, GeneratorIterator): + self.running = True + try: + return w_yf.throw(space, w_type, w_val, w_tb) + except OperationError as e: + operr = e + finally: + self.running = False else: try: w_throw = space.getattr(w_yf, space.wrap("throw")) @@ -215,22 +219,22 @@ self.running = True try: return space.call_function(w_throw, w_type, w_val, w_tb) - except OperationError as operr: - self.running = False - # Pop subiterator from stack. - w_subiter = self.frame.popvalue() - assert space.is_w(w_subiter, w_yf) - # Termination repetition of YIELD_FROM - self.frame.last_instr += 1 - if operr.match(space, space.w_StopIteration): - operr.normalize_exception(space) - w_val = space.getattr(operr.get_w_value(space), - space.wrap("value")) - return self.send_ex(w_val) - else: - return self.send_ex(space.w_None, operr) + except OperationError as e: + operr = e finally: self.running = False + # Pop subiterator from stack. + w_subiter = self.frame.popvalue() + assert space.is_w(w_subiter, w_yf) + # Termination repetition of YIELD_FROM + self.frame.last_instr += 1 + if operr.match(space, space.w_StopIteration): + operr.normalize_exception(space) + w_val = space.getattr(operr.get_w_value(space), + space.wrap("value")) + return self.send_ex(w_val) + else: + return self.send_ex(space.w_None, operr) def _throw_here(self, space, w_type, w_val, w_tb): from pypy.interpreter.pytraceback import check_traceback @@ -252,12 +256,22 @@ def descr_close(self): """close() -> raise GeneratorExit inside generator/coroutine.""" - _PyGen_yf().... if self.frame is None: return # nothing to do in this case space = self.space + w_yf = self._get_yield_from() + operr = OperationError(space.w_GeneratorExit, + space.call_function(space.w_GeneratorExit)) + if w_yf is not None: + self.running = True + try: + gen_close_iter(space, w_yf) + except OperationError as e: + operr = e + finally: + self.running = False try: - w_retval = self.send_ex..?..(space.w_GeneratorExit..) + w_retval = self.send_ex(space.w_None, operr) except OperationError as e: if e.match(space, space.w_StopIteration) or \ e.match(space, space.w_GeneratorExit): @@ -397,6 +411,22 @@ return self +def gen_close_iter(space, w_yf): + # This helper function is used by close() and throw() to + # close a subiterator being delegated to by yield-from. + if isinstance(w_yf, GeneratorIterator): + w_yf.descr_close() + else: + try: + w_close = space.getattr(w_yf, space.wrap("close")) + except OperationError as e: + if not e.match(space, space.w_AttributeError): + # aaaaaaaah but that's what CPython does too + e.write_unraisable(space, "generator/coroutine.close()") + else: + space.call_function(w_close) + + def get_printable_location_genentry(bytecode): return '%s <generator>' % (bytecode.get_repr(),) generatorentry_driver = jit.JitDriver(greens=['pycode'], _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit