[pypy-commit] pypy py3.5-corowrapper: in-progress

2016-09-16 Thread arigo
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)

2016-09-16 Thread arigo
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

2016-09-16 Thread arigo
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

2016-09-14 Thread arigo
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