Allow else after a while loop

This commit is contained in:
Rob Day 2017-09-13 22:31:28 +01:00
parent 51fb807cc9
commit 567fa14f1d
4 changed files with 44 additions and 1 deletions

1
NEWS
View File

@ -18,6 +18,7 @@ Changes from 0.13.0
* new `comment` macro * new `comment` macro
* support EDN `#_` syntax to discard the next term * support EDN `#_` syntax to discard the next term
* `return` has been implemented as a special form * `return` has been implemented as a special form
* `while` loops may now contain an `else` clause, like `for` loops
[ Bug Fixes ] [ Bug Fixes ]
* Numeric literals are no longer parsed as symbols when followed by a dot * Numeric literals are no longer parsed as symbols when followed by a dot

View File

@ -2146,12 +2146,20 @@ class HyASTCompiler(object):
expr.pop(0) # "while" expr.pop(0) # "while"
ret = self.compile(expr.pop(0)) ret = self.compile(expr.pop(0))
orel = Result()
# (while cond body (else …))
if expr and expr[-1][0] == HySymbol("else"):
else_expr = expr.pop()
for else_body in else_expr[1:]:
orel += self.compile(else_body)
orel += orel.expr_as_stmt()
body = self._compile_branch(expr) body = self._compile_branch(expr)
body += body.expr_as_stmt() body += body.expr_as_stmt()
ret += ast.While(test=ret.force_expr, ret += ast.While(test=ret.force_expr,
body=body.stmts, body=body.stmts,
orelse=[], orelse=orel.stmts,
lineno=expr.start_line, lineno=expr.start_line,
col_offset=expr.start_column) col_offset=expr.start_column)

View File

@ -324,6 +324,7 @@ def test_ast_bad_with():
def test_ast_valid_while(): def test_ast_valid_while():
"Make sure AST can't compile invalid while" "Make sure AST can't compile invalid while"
can_compile("(while foo bar)") can_compile("(while foo bar)")
can_compile("(while foo bar (else baz))")
def test_ast_valid_for(): def test_ast_valid_for():

View File

@ -266,6 +266,39 @@
(assert (= count 0)) (assert (= count 0))
(assert (= fact 120))) (assert (= fact 120)))
(defn test-while-loop-else []
(setv count 5)
(setv fact 1)
(setv myvariable 18)
(while (> count 0)
(setv fact (* fact count))
(setv count (- count 1))
(else (setv myvariable 26)))
(assert (= count 0))
(assert (= fact 120))
(assert (= myvariable 26))
; multiple statements in a while loop should work
(setv count 5)
(setv fact 1)
(setv myvariable 18)
(setv myothervariable 15)
(while (> count 0)
(setv fact (* fact count))
(setv count (- count 1))
(else (setv myvariable 26)
(setv myothervariable 24)))
(assert (= count 0))
(assert (= fact 120))
(assert (= myvariable 26))
(assert (= myothervariable 24))
; else clause shouldn't get run after a break
(while True
(break)
(else (setv myvariable 53)))
(assert (= myvariable 26)))
(defn test-branching [] (defn test-branching []
"NATIVE: test if branching" "NATIVE: test if branching"