Repository: hylang/hy

Issue:
In `try` bodies, expressions before the last are dropped
When using multiple expressions in the body of a `try` form, those that are function calls seem to be discarded by the compiler.  Given the following code sample:

``` hy
(setv val 0)
(print (try
         (+= val 1)
         (print "Check")
         val
         (except [Exception] -1)))
```

Executing with Hy 0.14.0 under Python 3.5.2 prints `1` but **not** `Check`.  Running `hy2py3` prints the following code:

``` python
val = 0
try:
    val += 1
    _hy_anon_var_1 = val
except Exception:
    _hy_anon_var_1 = -1
print(_hy_anon_var_1)
```

Using a `do` form solves the issue.  However, the documentation seems to suggest that multiple expressions are allowed in the `try` body; as well as #1427.


Discussion:
Yep, this is a bug and it's in master. (Remember to check master, not the last release, for bugs before reporting.) It looks like statements are kept (`(try (raise 1) (raise 2) (finally 1))`) but expressions are dropped (`(try x (raise 2) (finally 1))`).
Probably related to #1542. Whack-a-mole.

Resolving patch:
diff --git a/hy/compiler.py b/hy/compiler.py
--- a/hy/compiler.py
+++ b/hy/compiler.py
@@ -790,13 +790,14 @@ def compile_try_expression(self, expr):
         expr.pop(0)  # try
 
         # (try something somethingelse…)
-        body = Result()
+        body = []
         # 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))
+            body.append(expr.pop(0))
+        body = self._compile_branch(body)
 
         var = self.get_anon_var()
         name = asty.Name(expr, id=ast_str(var), ctx=ast.Store())
@@ -805,8 +806,6 @@ def compile_try_expression(self, expr):
         returnable = Result(expr=expr_name, temp_variables=[expr_name, name],
                             contains_yield=body.contains_yield)
 
-        if not all(expr):
-            raise HyTypeError(expr, "Empty list not allowed in `try'")
         handler_results = Result()
         handlers = []
         while expr and expr[0][0] == HySymbol("except"):
@@ -846,7 +845,6 @@ def compile_try_expression(self, expr):
 
         body += body.expr_as_stmt() if orelse else asty.Assign(
             expr, targets=[name], value=body.force_expr)
-
         body = body.stmts or [asty.Pass(expr)]
 
         if PY3:


Test patch:
diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy
--- a/tests/native_tests/language.hy
+++ b/tests/native_tests/language.hy
@@ -584,18 +584,27 @@
   (do))
 
 
-(defn test-exceptions []
-  "NATIVE: test Exceptions"
+(defn test-try []
 
   (try (do) (except []))
 
   (try (do) (except [IOError]) (except []))
 
-  ; test that multiple expressions in a try get evaluated
+  ; test that multiple statements in a try get evaluated
   (setv value 0)
   (try (+= value 1) (+= value 2)  (except [IOError]) (except []))
   (assert (= value 3))
 
+  ; test that multiple expressions in a try get evaluated
+  ; https://github.com/hylang/hy/issues/1584
+  (setv l [])
+  (defn f [] (.append l 1))
+  (try (f) (f) (f) (except [IOError]))
+  (assert (= l [1 1 1]))
+  (setv l [])
+  (try (f) (f) (f) (except [IOError]) (else (f)))
+  (assert (= l [1 1 1 1]))
+
   ;; Test correct (raise)
   (setv passed False)
   (try