Merge pull request #1427 from rkday/try_body

Allow multiple expressions in a try
This commit is contained in:
Kodi Arfer 2017-12-06 14:37:19 -08:00 committed by GitHub
commit 0baedaa5c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 10 deletions

1
NEWS
View File

@ -51,6 +51,7 @@ Changes from 0.13.0
a for loop a for loop
* `else` clauses in `for` and `while` are recognized more reliably * `else` clauses in `for` and `while` are recognized more reliably
* Argument destructuring no longer interferes with function docstrings. * Argument destructuring no longer interferes with function docstrings.
* Multiple expressions are now allowed in `try`
[ Misc. Improvements ] [ Misc. Improvements ]
* `read`, `read_str`, and `eval` are exposed and documented as top-level * `read`, `read_str`, and `eval` are exposed and documented as top-level

View File

@ -1666,6 +1666,7 @@ actions (``finally``).
(try (try
(error-prone-function) (error-prone-function)
(another-error-prone-function)
(except [ZeroDivisionError] (except [ZeroDivisionError]
(print "Division by zero")) (print "Division by zero"))
(except [[IndexError KeyboardInterrupt]] (except [[IndexError KeyboardInterrupt]]
@ -1679,13 +1680,13 @@ actions (``finally``).
(finally (finally
(print "All done"))) (print "All done")))
The first argument of ``try`` is its body. (To put more than one form in the The first argument of ``try`` is its body, which can contain one or more forms.
body, use ``do``.) Then comes any number of ``except`` clauses, then optionally Then comes any number of ``except`` clauses, then optionally an ``else``
an ``else`` clause, then optionally a ``finally`` clause. If an exception is clause, then optionally a ``finally`` clause. If an exception is raised with a
raised with a matching ``except`` clause during the execution of the body, that matching ``except`` clause during the execution of the body, that ``except``
``except`` clause will be executed. If no exceptions are raised, the ``else`` clause will be executed. If no exceptions are raised, the ``else`` clause is
clause is executed. The ``finally`` clause will be executed last regardless of executed. The ``finally`` clause will be executed last regardless of whether an
whether an exception was raised. exception was raised.
The return value of ``try`` is the last form of the ``except`` clause that was 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`` run, or the last form of ``else`` if no exception was raised, or the ``try``

View File

@ -843,8 +843,14 @@ class HyASTCompiler(object):
expr = copy.deepcopy(expr) expr = copy.deepcopy(expr)
expr.pop(0) # try expr.pop(0) # try
# (try something…) # (try something somethingelse…)
body = self.compile(expr.pop(0) if expr else []) 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() var = self.get_anon_var()
name = asty.Name(expr, id=ast_str(var), ctx=ast.Store()) name = asty.Name(expr, id=ast_str(var), ctx=ast.Store())

View File

@ -515,10 +515,16 @@
(try (do) (except [IOError]) (except)) (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) ;; Test correct (raise)
(setv passed False) (setv passed False)
(try (try
(try (try
(do)
(raise IndexError) (raise IndexError)
(except [IndexError] (raise))) (except [IndexError] (raise)))
(except [IndexError] (except [IndexError]
@ -650,7 +656,25 @@
(setv x 45)) (setv x 45))
(else (setv x 44))) (else (setv x 44)))
(except)) (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 [] (defn test-earmuffs []
"NATIVE: Test earmuffs" "NATIVE: Test earmuffs"