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:
parent
fb7c7e5794
commit
ea5eba5916
@ -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 != []:
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user