Implements `else' for `foreach' statements

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2013-04-14 20:22:38 +02:00
parent 403be35aa3
commit bbaab58a4c
3 changed files with 39 additions and 1 deletions

View File

@ -822,6 +822,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,
@ -830,7 +843,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

View File

@ -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]

View File

@ -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]))