diff --git a/hy/compiler.py b/hy/compiler.py index 3f1baf3..69596da 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -869,6 +869,19 @@ class HyASTCompiler(object): name, iterable = expression.pop(0) target = self._storeize(self.compile_symbol(name)) + orelse = [] + # (foreach [] body (else …)) + if expression and expression[-1][0] == HySymbol("else"): + else_expr = expression.pop() + if len(else_expr) > 2: + # XXX use HyTypeError as soon as it lands + raise TypeError("`else' statement in `foreach' is too long") + elif len(else_expr) == 2: + orelse = self._code_branch( + self.compile(else_expr[1]), + else_expr[1].start_line, + else_expr[1].start_column) + ret = ast.For(lineno=expression.start_line, col_offset=expression.start_column, target=target, @@ -877,7 +890,7 @@ class HyASTCompiler(object): [self.compile(x) for x in expression], expression.start_line, expression.start_column), - orelse=[]) + orelse=orelse) self.returnable = ret_status return ret diff --git a/tests/compilers/test_ast.py b/tests/compilers/test_ast.py index 05cf72b..2a738c7 100644 --- a/tests/compilers/test_ast.py +++ b/tests/compilers/test_ast.py @@ -273,6 +273,16 @@ def test_ast_valid_while(): hy_compile(tokenize("(while foo bar)")) +def test_ast_valid_foreach(): + "Make sure AST can compile valid foreach" + hy_compile(tokenize("(foreach [a 2])")) + + +def test_ast_invalid_foreach(): + "Make sure AST can't compile invalid foreach" + cant_compile("(foreach [a 1] (else 1 2))") + + def test_ast_expression_basics(): """ Ensure basic AST expression conversion works. """ code = hy_compile(tokenize("(foo bar)")).body[0] diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 45045c6..c1a1b6c 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -375,6 +375,21 @@ (assert (= y x 2))) +(defn test-foreach-else [] + "NATIVE: test foreach else" + (let [[x 0]] + (foreach [a [1 2]] + (setv x (+ x a)) + (else (setv x (+ x 50)))) + (assert (= x 53))) + + (let [[x 0]] + (foreach [a [1 2]] + (setv x (+ x a)) + (else)) + (assert (= x 3)))) + + (defn test-comprehensions [] "NATIVE: test list comprehensions" (assert (= (list-comp (* x 2) (x (range 2))) [0 2]))