merge branch 'assign_err' (from pull request #964)

This commit is contained in:
Zack M. Davis 2015-11-13 22:31:57 -08:00
commit 4d5eafb442
2 changed files with 53 additions and 16 deletions

View File

@ -590,21 +590,22 @@ class HyASTCompiler(object):
return ret, args, defaults, varargs, kwonlyargs, kwonlydefaults, kwargs 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""" """Return a new `name` object with an ast.Store() context"""
if not func: if not func:
func = ast.Store func = ast.Store
if isinstance(name, Result): if isinstance(name, Result):
if not name.is_expr(): 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 name = name.expr
if isinstance(name, (ast.Tuple, ast.List)): if isinstance(name, (ast.Tuple, ast.List)):
typ = type(name) typ = type(name)
new_elts = [] new_elts = []
for x in name.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) new_name = typ(elts=new_elts)
elif isinstance(name, ast.Name): elif isinstance(name, ast.Name):
new_name = ast.Name(id=name.id, arg=name.arg) new_name = ast.Name(id=name.id, arg=name.arg)
@ -613,7 +614,9 @@ class HyASTCompiler(object):
elif isinstance(name, ast.Attribute): elif isinstance(name, ast.Attribute):
new_name = ast.Attribute(value=name.value, attr=name.attr) new_name = ast.Attribute(value=name.value, attr=name.attr)
else: 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() new_name.ctx = func()
ast.copy_location(new_name, name) ast.copy_location(new_name, name)
@ -953,7 +956,7 @@ class HyASTCompiler(object):
name = ast_str(name) name = ast_str(name)
else: else:
# Python2 requires an ast.Name, set to ctx Store. # Python2 requires an ast.Name, set to ctx Store.
name = self._storeize(self.compile(name)) name = self._storeize(name, self.compile(name))
else: else:
name = None name = None
@ -1343,11 +1346,13 @@ class HyASTCompiler(object):
col_offset=root.start_column) col_offset=root.start_column)
return result return result
ld_targets, ret, _ = self._compile_collect(expr)
del_targets = [] del_targets = []
for target in ld_targets: ret = Result()
del_targets.append(self._storeize(target, ast.Del)) 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( return ret + ast.Delete(
lineno=expr.start_line, lineno=expr.start_line,
@ -1436,7 +1441,7 @@ class HyASTCompiler(object):
thing = None thing = None
if args != []: 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) body = self._compile_branch(expr)
@ -1498,7 +1503,7 @@ class HyASTCompiler(object):
gen = [] gen = []
for target, iterable in paired_gens: for target, iterable in paired_gens:
comp_target = self.compile(target) comp_target = self.compile(target)
target = self._storeize(comp_target) target = self._storeize(target, comp_target)
gen_res += self.compile(iterable) gen_res += self.compile(iterable)
gen.append(ast.comprehension( gen.append(ast.comprehension(
target=target, target=target,
@ -1963,7 +1968,7 @@ class HyASTCompiler(object):
op = ops[expression[0]] 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 = self.compile(expression[2])
ret += ast.AugAssign( ret += ast.AugAssign(
@ -2099,7 +2104,7 @@ class HyASTCompiler(object):
and '.' not in name: and '.' not in name:
result.rename(name) result.rename(name)
else: else:
st_name = self._storeize(ld_name) st_name = self._storeize(name, ld_name)
result += ast.Assign( result += ast.Assign(
lineno=start_line, lineno=start_line,
col_offset=start_column, col_offset=start_column,
@ -2127,7 +2132,7 @@ class HyASTCompiler(object):
raise HyTypeError(expression, raise HyTypeError(expression,
"for requires two forms in the list") "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() ret = Result()

View File

@ -1,7 +1,8 @@
(import [tests.resources [kwtest function-with-a-dash]] (import [tests.resources [kwtest function-with-a-dash]]
[os.path [exists isdir isfile]] [os.path [exists isdir isfile]]
[sys :as systest] [sys :as systest]
[operator [or_]]) [operator [or_]]
[hy.errors [HyTypeError]])
(import sys) (import sys)
(import [hy._compat [PY33 PY34 PY35]]) (import [hy._compat [PY33 PY34 PY35]])
@ -60,6 +61,7 @@
(setv (get foo 0) 12) (setv (get foo 0) 12)
(assert (= (get foo 0) 12))) (assert (= (get foo 0) 12)))
(defn test-setv-builtin [] (defn test-setv-builtin []
"NATIVE: test that setv doesn't work on builtins" "NATIVE: test that setv doesn't work on builtins"
(try (eval '(setv False 1)) (try (eval '(setv False 1))
@ -93,6 +95,37 @@
(except [e [TypeError]] (assert (in "`setv' needs an even number of arguments" (str e)))))) (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 [] (defn test-fn-corner-cases []
"NATIVE: tests that fn/defn handles corner cases gracefully" "NATIVE: tests that fn/defn handles corner cases gracefully"
(try (eval '(fn "foo")) (try (eval '(fn "foo"))
@ -965,7 +998,6 @@
(defn test-eval-failure [] (defn test-eval-failure []
"NATIVE: test eval failure modes" "NATIVE: test eval failure modes"
(import [hy.errors [HyTypeError]])
; yo dawg ; yo dawg
(try (eval '(eval)) (except [e HyTypeError]) (else (assert False))) (try (eval '(eval)) (except [e HyTypeError]) (else (assert False)))
(try (eval '(eval "snafu")) (except [e HyTypeError]) (else (assert False))) (try (eval '(eval "snafu")) (except [e HyTypeError]) (else (assert False)))