Second part of the fix for yield inside a try-finally

As noted in #600, Python 3 allows a return inside a generator
method, that raises a StopIteration and passes the return value
inside the 'value' attr of the exception.

To allow this behaviour we simple set 'contains_yield' while compiling
'yield', thus allowing a return statement, but only for Python 3. Then
when compiling the try-except, we check for contains_yield to decide
whether there will be a return.

This allows code like:

(defn gen []
  (yield 3)
  "goodbye")

to compile in both Py2 and Py3. The return value is simply ignored in
Python 2.

hy2py in Python 2 gives:

def g():
    yield 3L
    u'goodbye'

while hy2py in Python 3 gives:

def g():
    yield 3
    return 'goodbye'

Turns out return in yield started in Python 3.3
This commit is contained in:
Bob Tolbert 2014-06-22 14:33:39 -06:00
parent fb7c7e5794
commit ea5eba5916
2 changed files with 28 additions and 1 deletions

View File

@ -997,7 +997,10 @@ class HyASTCompiler(object):
@checkargs(max=1)
def compile_yield_expression(self, expr):
expr.pop(0)
ret = Result(contains_yield=True)
if PY33:
ret = Result(contains_yield=False)
else:
ret = Result(contains_yield=True)
value = None
if expr != []:

View File

@ -3,6 +3,7 @@
[sys :as systest])
(import sys)
(import [hy._compat [PY33 PY34]])
(defn test-sys-argv []
"NATIVE: test sys.argv"
@ -448,6 +449,29 @@
(for [y (gen)] (setv ret (+ ret y)))
(assert (= ret 10)))
(defn test-yield-with-return []
"NATIVE: test yield with return"
(defn gen [] (yield 3) "goodbye")
(if PY33
(do (setv gg (gen))
(assert (= 3 (next gg)))
(try (next gg)
(except [e StopIteration] (assert (hasattr e "value"))
(assert (= (getattr e "value") "goodbye")))))
(do (setv gg (gen))
(assert (= 3 (next gg)))
(try (next gg)
(except [e StopIteration] (assert (not (hasattr e "value"))))))))
(defn test-yield-in-try []
"NATIVE: test yield in try"
(defn gen []
(let [[x 1]]
(try (yield x)
(finally (print x)))))
(setv output (list (gen)))
(assert (= [1] output)))
(defn test-first []
"NATIVE: test firsty things"