From ec1c92bf4e2b224d70c24e34fa5569478bd9e9c4 Mon Sep 17 00:00:00 2001 From: Kodi Arfer Date: Sun, 15 Apr 2018 15:59:35 -0700 Subject: [PATCH] Allow `for` with an empty body --- NEWS.rst | 1 + hy/compiler.py | 2 +- hy/core/macros.hy | 6 +----- tests/compilers/test_ast.py | 8 -------- tests/native_tests/language.hy | 10 +++++++++- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/NEWS.rst b/NEWS.rst index 57d69a7..c1a673b 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -39,6 +39,7 @@ New Features * `defclass` in Python 3 now supports specifying metaclasses and other keyword arguments * Added a command-line option `-E` per CPython +* `while` and `for` are allowed to have empty bodies Bug Fixes ------------------------------ diff --git a/hy/compiler.py b/hy/compiler.py index 0f92131..91344ba 100755 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1820,7 +1820,7 @@ class HyASTCompiler(object): ret += node(expression, target=target, iter=ret.force_expr, - body=body.stmts, + body=body.stmts or [asty.Pass(expression)], orelse=orel.stmts) ret.contains_yield = body.contains_yield diff --git a/hy/core/macros.hy b/hy/core/macros.hy index 16432dd..a948fd8 100644 --- a/hy/core/macros.hy +++ b/hy/core/macros.hy @@ -110,15 +110,11 @@ used as the result." (defn _for [node args body] (setv body (list body)) - (if (empty? body) - (macro-error None "`for' requires a body to evaluate")) - (setv lst (get body -1)) - (setv belse (if (and (isinstance lst HyExpression) (= (get lst 0) "else")) + (setv belse (if (and body (isinstance (get body -1) HyExpression) (= (get body -1 0) "else")) [(body.pop)] [])) (if (odd? (len args)) (macro-error args "`for' requires an even number of args.") - (empty? body) (macro-error None "`for' requires a body to evaluate") (empty? args) `(do ~@body ~@belse) (= (len args) 2) `(~node [~@args] (do ~@body) ~@belse) (do diff --git a/tests/compilers/test_ast.py b/tests/compilers/test_ast.py index faaa772..c8d2999 100644 --- a/tests/compilers/test_ast.py +++ b/tests/compilers/test_ast.py @@ -534,14 +534,6 @@ def test_for_compile_error(): can_compile("(fn [] (for [x] x))") assert excinfo.value.message == "`for' requires an even number of args." - with pytest.raises(HyTypeError) as excinfo: - can_compile("(fn [] (for [x xx]))") - assert excinfo.value.message == "`for' requires a body to evaluate" - - with pytest.raises(HyTypeError) as excinfo: - can_compile("(fn [] (for [x xx] (else 1)))") - assert excinfo.value.message == "`for' requires a body to evaluate" - def test_attribute_access(): """Ensure attribute access compiles correctly""" diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index d76102c..d742c91 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -232,7 +232,15 @@ (assert (= (list ((fn [] (for [x [[1] [2 3]] y x] (yield y))))) (list-comp y [x [[1] [2 3]] y x]))) (assert (= (list ((fn [] (for [x [[1] [2 3]] y x z (range 5)] (yield z))))) - (list-comp z [x [[1] [2 3]] y x z (range 5)])))) + (list-comp z [x [[1] [2 3]] y x z (range 5)]))) + + (setv l []) + (defn f [] + (for [x [4 9 2]] + (.append l (* 10 x)) + (yield x))) + (for [_ (f)]) + (assert (= l [40 90 20]))) (defn test-nasty-for-nesting []