diff --git a/NEWS b/NEWS index 4842f24..1ab7dc8 100644 --- a/NEWS +++ b/NEWS @@ -51,6 +51,7 @@ Changes from 0.13.0 a for loop * `else` clauses in `for` and `while` are recognized more reliably * Argument destructuring no longer interferes with function docstrings. + * Multiple expressions are now allowed in `try` [ Misc. Improvements ] * `read`, `read_str`, and `eval` are exposed and documented as top-level diff --git a/docs/language/api.rst b/docs/language/api.rst index 71e03dc..cfc8bab 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -1666,6 +1666,7 @@ actions (``finally``). (try (error-prone-function) + (another-error-prone-function) (except [ZeroDivisionError] (print "Division by zero")) (except [[IndexError KeyboardInterrupt]] @@ -1679,13 +1680,13 @@ actions (``finally``). (finally (print "All done"))) -The first argument of ``try`` is its body. (To put more than one form in the -body, use ``do``.) Then comes any number of ``except`` clauses, then optionally -an ``else`` clause, then optionally a ``finally`` clause. If an exception is -raised with a matching ``except`` clause during the execution of the body, that -``except`` clause will be executed. If no exceptions are raised, the ``else`` -clause is executed. The ``finally`` clause will be executed last regardless of -whether an exception was raised. +The first argument of ``try`` is its body, which can contain one or more forms. +Then comes any number of ``except`` clauses, then optionally an ``else`` +clause, then optionally a ``finally`` clause. If an exception is raised with a +matching ``except`` clause during the execution of the body, that ``except`` +clause will be executed. If no exceptions are raised, the ``else`` clause is +executed. The ``finally`` clause will be executed last regardless of whether an +exception was raised. The return value of ``try`` is the last form of the ``except`` clause that was run, or the last form of ``else`` if no exception was raised, or the ``try`` diff --git a/hy/compiler.py b/hy/compiler.py index ccd28e4..9fe6265 100755 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -843,8 +843,14 @@ class HyASTCompiler(object): expr = copy.deepcopy(expr) expr.pop(0) # try - # (try something…) - body = self.compile(expr.pop(0) if expr else []) + # (try something somethingelse…) + body = Result() + # Check against HyExpression and HySymbol to avoid incorrectly + # matching [except ...] or ("except" ...) + while expr and not (isinstance(expr[0], HyExpression) + and isinstance(expr[0][0], HySymbol) + and expr[0][0] in ("except", "else", "finally")): + body += self.compile(expr.pop(0)) var = self.get_anon_var() name = asty.Name(expr, id=ast_str(var), ctx=ast.Store()) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 42f27cb..703e083 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -515,10 +515,16 @@ (try (do) (except [IOError]) (except)) + ; test that multiple expressions in a try get evaluated + (setv value 0) + (try (+= value 1) (+= value 2) (except [IOError]) (except)) + (assert (= value 3)) + ;; Test correct (raise) (setv passed False) (try (try + (do) (raise IndexError) (except [IndexError] (raise))) (except [IndexError] @@ -650,7 +656,25 @@ (setv x 45)) (else (setv x 44))) (except)) - (assert (= x 0))) + (assert (= x 0)) + + ; test that [except ...] and ("except" ...) aren't treated like (except ...), + ; and that the code there is evaluated normally + (setv x 0) + (try + (+= x 1) + ("except" [IOError] (+= x 1)) + (except)) + + (assert (= x 2)) + + (setv x 0) + (try + (+= x 1) + [except [IOError] (+= x 1)] + (except)) + + (assert (= x 2))) (defn test-earmuffs [] "NATIVE: Test earmuffs"