[pypy-commit] pypy py3.5-corowrapper: in-progress
Author: Armin Rigo Branch: py3.5-corowrapper Changeset: r87145:7a673159303f Date: 2016-09-16 19:02 +0200 http://bitbucket.org/pypy/pypy/changeset/7a673159303f/ 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 @@ -4,13 +4,13 @@ from pypy.interpreter.pycode import CO_YIELD_INSIDE_TRY from pypy.interpreter.astcompiler import consts from rpython.rlib import jit +from rpython.rlib.objectmodel import specialize class GeneratorOrCoroutine(W_Root): _immutable_fields_ = ['pycode'] w_yielded_from = None -thrown_operr = None def __init__(self, frame, name=None, qualname=None): self.space = frame.space @@ -113,18 +113,17 @@ raise operr w_result = self._invoke_execute_frame(frame, w_arg_or_err) +assert w_result is not None # if the frame is now marked as finished, it was RETURNed from if frame.frame_finished_execution: self.frame = None -if space.is_none(w_result): -# Delay exception instantiation if we can +if space.is_w(w_result, space.w_None): raise OperationError(space.w_StopIteration, space.w_None) else: raise OperationError(space.w_StopIteration, - space.newtuple([w_result])) +space.call_function(space.w_StopIteration, w_result)) else: -assert w_result is not None return w_result # YIELDed def _invoke_execute_frame(self, frame, w_arg_or_err): @@ -186,9 +185,10 @@ elif space.is_w(w_inputvalue_or_err, space.w_None): w_retval = space.next(w_yf) elif isinstance(w_inputvalue_or_err, SApplicationException): -raise w_inputvalue_or_err.operr +operr = w_inputvalue_or_err.operr +X else: -w_retval = space.call_method(w_gen, "send", w_inputvalue_or_err) +w_retval = space.call_method(w_yf, "send", w_inputvalue_or_err) except OperationError as e: self.w_yielded_from = None if not e.match(space, space.w_StopIteration): @@ -229,13 +229,11 @@ def descr_throw(self, w_type, w_val=None, w_tb=None): """throw(typ[,val[,tb]]) -> raise exception in generator/coroutine, return next yielded value or raise StopIteration.""" +from pypy.interpreter.pytraceback import check_traceback + +space = self.space if w_val is None: -w_val = self.space.w_None -return self.throw(w_type, w_val, w_tb) - -def throw(self, w_type, w_val, w_tb): -from pypy.interpreter.pytraceback import check_traceback -space = self.space +w_val = space.w_None msg = "throw() third argument must be a traceback object" if space.is_none(w_tb): @@ -244,6 +242,15 @@ tb = check_traceback(space, w_tb, msg) operr = OperationError(w_type, w_val, tb) +w_yf = self.w_yielded_from +if (w_yf is not None and +operr.match(space, space.w_GeneratorExit)): +self.w_yielded_from = None +try: +gen_close_iter(space, w_yf) +except OperationError as e: +return self.send_error(e) + operr.normalize_exception(space) if tb is None: tb = space.getattr(operr.get_w_value(space), @@ -257,18 +264,14 @@ if self.frame is None: return # nothing to do in this case space = self.space -operr = OperationError(space.w_GeneratorExit, - space.call_function(space.w_GeneratorExit)) +operr = get_generator_exit(space) w_yf = self.w_yielded_from if w_yf is not None: -XXX -self.running = True +self.w_yielded_from = None try: gen_close_iter(space, w_yf) except OperationError as e: operr = e -finally: -self.running = False try: self.send_error(operr) except OperationError as e: @@ -402,6 +405,11 @@ return self +@specialize.memo() +def get_generator_exit(space): +return OperationError(space.w_GeneratorExit, + space.call_function(space.w_GeneratorExit)) + 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. ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5-corowrapper: in-progress (I think that basic generators are working again)
Author: Armin Rigo Branch: py3.5-corowrapper Changeset: r87140:97a825be3993 Date: 2016-09-16 16:26 +0200 http://bitbucket.org/pypy/pypy/changeset/97a825be3993/ Log:in-progress (I think that basic generators are working again) diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py --- a/pypy/interpreter/generator.py +++ b/pypy/interpreter/generator.py @@ -83,6 +83,9 @@ return next yielded value or raise StopIteration.""" return self.send_ex(w_arg) +def send_error(self, operr): +return self.send_ex(SApplicationException(operr)) + def send_ex(self, w_arg_or_err): assert w_arg_or_err is not None pycode = self.pycode @@ -95,8 +98,6 @@ def _send_ex(self, w_arg_or_err): space = self.space -if self.running: -raise oefmt(space.w_ValueError, "%s already executing", self.KIND) frame = self.frame if frame is None: @@ -127,6 +128,8 @@ def _invoke_execute_frame(self, frame, w_arg_or_err): space = self.space +if self.running: +raise oefmt(space.w_ValueError, "%s already executing", self.KIND) self.running = True try: w_result = frame.execute_frame(self, w_arg_or_err) @@ -210,7 +213,7 @@ finally: self.running = False except OperationError as e: -return self.send_ex(space.w_None, e) +return self.send_error(e) return self._throw_here(space, w_type, w_val, w_tb) # if isinstance(w_yf, GeneratorIterator): @@ -246,7 +249,7 @@ space.wrap("value")) return self.send_ex(w_val) else: -return self.send_ex(space.w_None, operr) +return self.send_error(operr) def _throw_here(self, space, w_type, w_val, w_tb): from pypy.interpreter.pytraceback import check_traceback @@ -264,16 +267,16 @@ space.wrap('__traceback__')) if not space.is_w(tb, space.w_None): operr.set_traceback(tb) -return self.send_ex(SApplicationException(operr)) +return self.send_error(operr) def descr_close(self): """close() -> raise GeneratorExit inside generator/coroutine.""" 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)) +w_yf = self.w_yielded_from if w_yf is not None: self.running = True try: @@ -283,7 +286,7 @@ finally: self.running = False try: -w_retval = self.send_ex(space.w_None, operr) +w_retval = self.send_error(operr) except OperationError as e: if e.match(space, space.w_StopIteration) or \ e.match(space, space.w_GeneratorExit): @@ -344,34 +347,26 @@ def unpack_into(self, results): """This is a hack for performance: runs the generator and collects all produced items in a list.""" -# XXX copied and simplified version of send_ex() -space = self.space -if self.running: -raise oefmt(space.w_ValueError, "generator already executing") frame = self.frame if frame is None:# already finished return -self.running = True -try: -pycode = self.pycode -while True: -jitdriver.jit_merge_point(self=self, frame=frame, - results=results, pycode=pycode) -try: -w_result = self._invoke_execute_frame( -frame, space.w_None) -except OperationError as e: -if not e.match(space, space.w_StopIteration): -raise -break -# if the frame is now marked as finished, it was RETURNed from -if frame.frame_finished_execution: -break -results.append(w_result) # YIELDed -finally: -frame.f_backref = jit.vref_None -self.running = False -self.frame = None +pycode = self.pycode +while True: +jitdriver.jit_merge_point(self=self, frame=frame, + results=results, pycode=pycode) +space = self.space +try: +w_result = self._invoke_execute_frame( +frame, space.w_None) +excep
[pypy-commit] pypy py3.5-corowrapper: in-progress
Author: Armin Rigo 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_re
[pypy-commit] pypy py3.5-corowrapper: in-progress
Author: Armin Rigo Branch: py3.5-corowrapper Changeset: r87113:a1f0e3bcdc6f Date: 2016-09-14 19:35 +0200 http://bitbucket.org/pypy/pypy/changeset/a1f0e3bcdc6f/ 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 @@ -7,38 +7,41 @@ class GeneratorOrCoroutine(W_Root): -"""XXX: move the common functionality here!""" - -def descr_close(self): -raise NotImplementedError - - -class GeneratorIterator(GeneratorOrCoroutine): -"An iterator created by a generator." _immutable_fields_ = ['pycode'] -def __init__(self, frame): +def __init__(self, frame, name=None, qualname=None): self.space = frame.space self.frame = frame # turned into None when frame_finished_execution -self.pycode = frame.pycode +self.pycode = frame.pycode # usually never None but see __setstate__ self.running = False +self._name = name # may be null, use get_name() +self._qualname = qualname # may be null, use get_qualname() if self.pycode.co_flags & CO_YIELD_INSIDE_TRY: self.register_finalizer(self.space) +def get_name(self): +if self._name is not None: +return self._name +elif self.pycode is None: +return "" +else: +return self.pycode.co_name + +def get_qualname(self): +if self._qualname is not None: +return self._qualname +return self.get_name() + def descr__repr__(self, space): -if self.pycode is None: -code_name = '' -else: -code_name = self.pycode.co_name addrstring = self.getaddrstring(space) -return space.wrap("" % - (code_name, addrstring)) +return space.wrap("<%s object %s at 0x%s>" % + (self.KIND, self.get_qualname(), addrstring)) def descr__reduce__(self, space): from pypy.interpreter.mixedmodule import MixedModule w_mod= space.getbuiltinmodule('_pickle_support') mod = space.interp_w(MixedModule, w_mod) -new_inst = mod.get('generator_new') +new_inst = mod.get(self.KIND + '_new') w= space.wrap if self.frame: w_frame = self.frame._reduce_state(space) @@ -64,15 +67,16 @@ else: frame = instantiate(space.FrameClass) # XXX fish frame.descr__setstate__(space, w_framestate) -GeneratorIterator.__init__(self, frame) +if isinstance(self, GeneratorIterator): +GeneratorIterator.__init__(self, frame) +elif isinstance(self, Coroutine): +Coroutine.__init__(self, frame) +else: +assert False self.running = self.space.is_true(w_running) -def descr__iter__(self): -"""x.__iter__() <==> iter(x)""" -return self.space.wrap(self) - def descr_send(self, w_arg=None): -"""send(arg) -> send 'arg' into generator, +"""send(arg) -> send 'arg' into generator/coroutine, return next yielded value or raise StopIteration.""" return self.send_ex(w_arg) @@ -87,9 +91,12 @@ def _send_ex(self, w_arg, operr): space = self.space if self.running: -raise oefmt(space.w_ValueError, "generator already executing") +raise oefmt(space.w_ValueError, "%s already executing", self.KIND) frame = self.frame if frame is None: +if isinstance(self, Coroutine): +raise oefmt(space.w_RuntimeError, +"cannot reuse already awaited coroutine") # xxx a bit ad-hoc, but we don't want to go inside # execute_frame() if the frame is actually finished if operr is None: @@ -100,8 +107,8 @@ if last_instr == -1: if w_arg and not space.is_w(w_arg, space.w_None): raise oefmt(space.w_TypeError, -"can't send non-None value to a just-started " -"generator") +"can't send non-None value to a just-started %s", +self.KIND) else: if not w_arg: w_arg = space.w_None @@ -129,7 +136,7 @@ self.running = False def descr_throw(self, w_type, w_val=None, w_tb=None): -"""x.throw(typ[,val[,tb]]) -> raise exception in generator, +"""throw(typ[,val[,tb]]) -> raise exception in generator/coroutine, return next yielded value or raise StopIteration.""" if w_val is None: w_val = self.space.w_None @@ -219,16 +226,14 @@ operr.set_traceback(tb) return self.send_ex(space.w_None, operr) -def descr_next(self): -"""x.__next__() <==> next(x)""" -r