From d070d3d484f063ab240de978eed6028a59ad1a89 Mon Sep 17 00:00:00 2001 From: Nicolas Dandrimont Date: Wed, 3 Apr 2013 19:55:09 +0200 Subject: [PATCH] Add while loops to the compiler --- TODO | 3 --- hy/compiler.py | 20 ++++++++++++++++++++ tests/compilers/test_ast.py | 23 +++++++++++++++++++++++ tests/native_tests/language.hy | 11 +++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index bf2c64d..5d29fb0 100644 --- a/TODO +++ b/TODO @@ -9,9 +9,6 @@ + Use (def) to imply global foo - - New Builtins: - + While - - New macros: + loop diff --git a/hy/compiler.py b/hy/compiler.py index e860195..9e98af5 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -545,6 +545,26 @@ class HyASTCompiler(object): self.returnable = ret_status return ret + @builds("while") + def compile_while_expression(self, expr): + expr.pop(0) # "while" + + try: + test = expr.pop(0) + except IndexError: + raise TypeError("while expects at least 2 arguments, got 0") + test = self.compile(test) + + if not expr: + raise TypeError("while expects a body") + + return ast.While(test=test, + body=self._mangle_branch([ + self.compile(x) for x in expr]), + orelse=[], + lineno=expr.start_line, + col_offset=expr.start_column) + @builds(HyList) def compile_list(self, expr): return ast.List( diff --git a/tests/compilers/test_ast.py b/tests/compilers/test_ast.py index 8714486..88208d1 100644 --- a/tests/compilers/test_ast.py +++ b/tests/compilers/test_ast.py @@ -66,6 +66,29 @@ def test_ast_valid_if(): hy_compile(tokenize("(if foo bar)")) +def test_ast_bad_while_0_arg(): + "Make sure AST can't compile invalid while" + try: + hy_compile(tokenize("(while)")) + assert False + except TypeError: + pass + + +def test_ast_bad_while_1_arg(): + "Make sure AST can't compile invalid while" + try: + hy_compile(tokenize("(while (true))")) + assert False + except TypeError: + pass + + +def test_ast_valid_while(): + "Make sure AST can't compile invalid while" + hy_compile(tokenize("(while foo bar)")) + + 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 2d5ecd3..ffc6109 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -32,6 +32,17 @@ (assert (= count 150))) +(defn test-while-loop [] + "NATIVE: test while loops?" + (setv count 5) + (setv fact 1) + (while (> count 0) + (setv fact (* fact count)) + (setv count (- count 1))) + (assert (= count 0)) + (assert (= fact 120))) + + (defn test-in [] "NATIVE: test in" (assert (in "a" ["a" "b" "c" "d"]))