diff --git a/hy/compiler.py b/hy/compiler.py index a82d89e..b1fd266 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -47,6 +47,7 @@ import importlib import codecs import ast import sys +import keyword from collections import defaultdict @@ -73,6 +74,21 @@ def load_stdlib(): _stdlib[e] = module +# True, False and None included here since they +# are assignable in Python 2.* but become +# keywords in Python 3.* +def _is_hy_builtin(name, module_name): + extras = ['True', 'False', 'None', + 'true', 'false', 'nil', 'null'] + if name in extras or keyword.iskeyword(name): + return True + # for non-Hy modules, check for pre-existing name in + # _compile_table + if not module_name.startswith("hy."): + return name in _compile_table + return False + + _compile_table = {} @@ -1751,6 +1767,12 @@ class HyASTCompiler(object): def _compile_assign(self, name, result, start_line, start_column): + + str_name = "%s" % name + if _is_hy_builtin(str_name, self.module_name): + raise HyTypeError(name, + "Can't assign to a builtin: `%s'" % str_name) + result = self.compile(result) ld_name = self.compile(name) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 7db5320..b7888e2 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -28,6 +28,28 @@ (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)) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(setv True 0)) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(setv None 1)) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(setv false 1)) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(setv true 0)) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(setv nil 1)) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(setv null 1)) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(defn defclass [] (print "hello"))) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(defn get [] (print "hello"))) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e))))) + (try (eval '(defn lambda [] (print "hello"))) + (catch [e [TypeError]] (assert (in "Can't assign to a builtin" (str e)))))) (defn test-for-loop [] "NATIVE: test for loops"