From 283111b4952650e02a2d862028eab5893388d608 Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Wed, 14 Oct 2015 12:38:05 -0500 Subject: [PATCH] Improve error messages related to _storeize --- hy/compiler.py | 33 ++++++++++++++++++------------- tests/native_tests/language.hy | 36 ++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/hy/compiler.py b/hy/compiler.py index 8032153..8259a2c 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -590,21 +590,22 @@ class HyASTCompiler(object): return ret, args, defaults, varargs, kwonlyargs, kwonlydefaults, kwargs - def _storeize(self, name, func=None): + def _storeize(self, expr, name, func=None): """Return a new `name` object with an ast.Store() context""" if not func: func = ast.Store if isinstance(name, Result): if not name.is_expr(): - raise TypeError("Can't assign / delete a non-expression") + raise HyTypeError(expr, + "Can't assign or delete a non-expression") name = name.expr if isinstance(name, (ast.Tuple, ast.List)): typ = type(name) new_elts = [] for x in name.elts: - new_elts.append(self._storeize(x, func)) + new_elts.append(self._storeize(expr, x, func)) new_name = typ(elts=new_elts) elif isinstance(name, ast.Name): new_name = ast.Name(id=name.id, arg=name.arg) @@ -613,7 +614,9 @@ class HyASTCompiler(object): elif isinstance(name, ast.Attribute): new_name = ast.Attribute(value=name.value, attr=name.attr) else: - raise TypeError("Can't assign / delete a %s object" % type(name)) + raise HyTypeError(expr, + "Can't assign or delete a %s" % + type(expr).__name__) new_name.ctx = func() ast.copy_location(new_name, name) @@ -953,7 +956,7 @@ class HyASTCompiler(object): name = ast_str(name) else: # Python2 requires an ast.Name, set to ctx Store. - name = self._storeize(self.compile(name)) + name = self._storeize(name, self.compile(name)) else: name = None @@ -1343,11 +1346,13 @@ class HyASTCompiler(object): col_offset=root.start_column) return result - ld_targets, ret, _ = self._compile_collect(expr) - del_targets = [] - for target in ld_targets: - del_targets.append(self._storeize(target, ast.Del)) + ret = Result() + for target in expr: + compiled_target = self.compile(target) + ret += compiled_target + del_targets.append(self._storeize(target, compiled_target, + ast.Del)) return ret + ast.Delete( lineno=expr.start_line, @@ -1436,7 +1441,7 @@ class HyASTCompiler(object): thing = None if args != []: - thing = self._storeize(self.compile(args.pop(0))) + thing = self._storeize(args[0], self.compile(args.pop(0))) body = self._compile_branch(expr) @@ -1498,7 +1503,7 @@ class HyASTCompiler(object): gen = [] for target, iterable in paired_gens: comp_target = self.compile(target) - target = self._storeize(comp_target) + target = self._storeize(target, comp_target) gen_res += self.compile(iterable) gen.append(ast.comprehension( target=target, @@ -1963,7 +1968,7 @@ class HyASTCompiler(object): op = ops[expression[0]] - target = self._storeize(self.compile(expression[1])) + target = self._storeize(expression[1], self.compile(expression[1])) ret = self.compile(expression[2]) ret += ast.AugAssign( @@ -2099,7 +2104,7 @@ class HyASTCompiler(object): and '.' not in name: result.rename(name) else: - st_name = self._storeize(ld_name) + st_name = self._storeize(name, ld_name) result += ast.Assign( lineno=start_line, col_offset=start_column, @@ -2127,7 +2132,7 @@ class HyASTCompiler(object): raise HyTypeError(expression, "for requires two forms in the list") - target = self._storeize(self.compile(target_name)) + target = self._storeize(target_name, self.compile(target_name)) ret = Result() diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 8c7533a..4bb4b45 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -1,7 +1,8 @@ (import [tests.resources [kwtest function-with-a-dash]] [os.path [exists isdir isfile]] [sys :as systest] - [operator [or_]]) + [operator [or_]] + [hy.errors [HyTypeError]]) (import sys) (import [hy._compat [PY33 PY34 PY35]]) @@ -60,6 +61,7 @@ (setv (get foo 0) 12) (assert (= (get foo 0) 12))) + (defn test-setv-builtin [] "NATIVE: test that setv doesn't work on builtins" (try (eval '(setv False 1)) @@ -93,6 +95,37 @@ (except [e [TypeError]] (assert (in "`setv' needs an even number of arguments" (str e)))))) +(defn test-store-errors [] + "NATIVE: test that setv raises the correct errors when given wrong argument types" + (try + (do + (eval '(setv (do 1 2) 1)) + (assert false)) + (except [e HyTypeError] + (assert (= e.message "Can't assign or delete a non-expression")))) + + (try + (do + (eval '(setv 1 1)) + (assert false)) + (except [e HyTypeError] + (assert (= e.message "Can't assign or delete a HyInteger")))) + + (try + (do + (eval '(setv {1 2} 1)) + (assert false)) + (except [e HyTypeError] + (assert (= e.message "Can't assign or delete a HyDict")))) + + (try + (do + (eval '(del 1 1)) + (assert false)) + (except [e HyTypeError] + (assert (= e.message "Can't assign or delete a HyInteger"))))) + + (defn test-fn-corner-cases [] "NATIVE: tests that fn/defn handles corner cases gracefully" (try (eval '(fn "foo")) @@ -965,7 +998,6 @@ (defn test-eval-failure [] "NATIVE: test eval failure modes" - (import [hy.errors [HyTypeError]]) ; yo dawg (try (eval '(eval)) (except [e HyTypeError]) (else (assert False))) (try (eval '(eval "snafu")) (except [e HyTypeError]) (else (assert False)))