From d99cf809866974eac317927f43431ef9028eacec Mon Sep 17 00:00:00 2001 From: Kodi Arfer Date: Mon, 8 Jul 2019 15:41:13 -0400 Subject: [PATCH] Run statements in the second argument of `assert` I've edited the test to use a list instead of a set because the order of evaluation probably ought to be guaranteed. --- NEWS.rst | 4 ++++ hy/compiler.py | 21 ++++++++++++++++----- tests/native_tests/language.hy | 7 +++---- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/NEWS.rst b/NEWS.rst index a0a00a9..5b30c1a 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -9,6 +9,10 @@ Removals * Support for attribute lists in `defclass` has been removed. Use `setv` and `defn` instead. +Bug Fixes +------------------------------ +* Statements in the second argument of `assert` are now executed. + 0.17.0 ============================== diff --git a/hy/compiler.py b/hy/compiler.py index bb1da22..7f81f6b 100755 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -820,11 +820,22 @@ class HyASTCompiler(object): @special("assert", [FORM, maybe(FORM)]) def compile_assert_expression(self, expr, root, test, msg): - ret = self.compile(test) - e = ret.force_expr - if msg is not None: - msg = self.compile(msg).force_expr - return ret + asty.Assert(expr, test=e, msg=msg) + if msg is None or type(msg) is HySymbol: + ret = self.compile(test) + return ret + asty.Assert( + expr, + test=ret.force_expr, + msg=(None if msg is None else self.compile(msg).force_expr)) + + # The `msg` part may involve statements, which we only + # want to be executed if the assertion fails. Rewrite the + # form to set `msg` to a variable. + msg_var = self.get_anon_var() + return self.compile(mkexpr( + 'if*', mkexpr('and', '__debug__', mkexpr('not', [test])), + mkexpr('do', + mkexpr('setv', msg_var, [msg]), + mkexpr('assert', 'False', msg_var))).replace(expr)) @special(["global", "nonlocal"], [oneplus(SYM)]) def compile_global_or_nonlocal(self, expr, root, syms): diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index e251840..707ecf0 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -1653,16 +1653,15 @@ macros() (= (identify-keywords 1 "bloo" :foo) ["other" "other" "keyword"]))) -#@(pytest.mark.xfail (defn test-assert-multistatements [] ; https://github.com/hylang/hy/issues/1390 - (setv s (set)) + (setv l []) (defn f [x] - (.add s x) + (.append l x) False) (with [(pytest.raises AssertionError)] (assert (do (f 1) (f 2)) (do (f 3) (f 4)))) - (assert (= s #{1 2 3 4})))) + (assert (= l [1 2 3 4]))) (defn test-underscore_variables [] ; https://github.com/hylang/hy/issues/1340