Allow defclass to have properties/method with built-in names
To allow classes to have methods that match built-in names, yet, still disallow them outside of defclass, keep an internal state whether builtins are allowed in the current context. By default, this is false. But defclass will set it to True when it compiles its body, and set it back to the previous value when it's done with that. We need to set back to the previous value to allow nested defclasses to work properly. This closes #783. Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This commit is contained in:
parent
9bff606ee9
commit
b92049d119
@ -370,6 +370,7 @@ def checkargs(exact=None, min=None, max=None, even=None, multiple=None):
|
|||||||
class HyASTCompiler(object):
|
class HyASTCompiler(object):
|
||||||
|
|
||||||
def __init__(self, module_name):
|
def __init__(self, module_name):
|
||||||
|
self.allow_builtins = False
|
||||||
self.anon_fn_count = 0
|
self.anon_fn_count = 0
|
||||||
self.anon_var_count = 0
|
self.anon_var_count = 0
|
||||||
self.imports = defaultdict(set)
|
self.imports = defaultdict(set)
|
||||||
@ -2005,7 +2006,8 @@ class HyASTCompiler(object):
|
|||||||
start_line, start_column):
|
start_line, start_column):
|
||||||
|
|
||||||
str_name = "%s" % name
|
str_name = "%s" % name
|
||||||
if _is_hy_builtin(str_name, self.module_name):
|
if _is_hy_builtin(str_name, self.module_name) and \
|
||||||
|
not self.allow_builtins:
|
||||||
raise HyTypeError(name,
|
raise HyTypeError(name,
|
||||||
"Can't assign to a builtin: `%s'" % str_name)
|
"Can't assign to a builtin: `%s'" % str_name)
|
||||||
|
|
||||||
@ -2275,6 +2277,8 @@ class HyASTCompiler(object):
|
|||||||
docstring.start_column)
|
docstring.start_column)
|
||||||
body += body.expr_as_stmt()
|
body += body.expr_as_stmt()
|
||||||
|
|
||||||
|
allow_builtins = self.allow_builtins
|
||||||
|
self.allow_builtins = True
|
||||||
if expressions and isinstance(expressions[0], HyList) \
|
if expressions and isinstance(expressions[0], HyList) \
|
||||||
and not isinstance(expressions[0], HyExpression):
|
and not isinstance(expressions[0], HyExpression):
|
||||||
expr = expressions.pop(0)
|
expr = expressions.pop(0)
|
||||||
@ -2287,6 +2291,8 @@ class HyASTCompiler(object):
|
|||||||
for expression in expressions:
|
for expression in expressions:
|
||||||
body += self.compile(macroexpand(expression, self.module_name))
|
body += self.compile(macroexpand(expression, self.module_name))
|
||||||
|
|
||||||
|
self.allow_builtins = allow_builtins
|
||||||
|
|
||||||
if not body.stmts:
|
if not body.stmts:
|
||||||
body += ast.Pass(lineno=expressions.start_line,
|
body += ast.Pass(lineno=expressions.start_line,
|
||||||
col_offset=expressions.start_column)
|
col_offset=expressions.start_column)
|
||||||
|
@ -554,6 +554,14 @@ def test_defn():
|
|||||||
|
|
||||||
|
|
||||||
def test_setv_builtins():
|
def test_setv_builtins():
|
||||||
"""Ensure that assigning to a builtin fails"""
|
"""Ensure that assigning to a builtin fails, unless in a class"""
|
||||||
cant_compile("(setv nil 42)")
|
cant_compile("(setv nil 42)")
|
||||||
cant_compile("(defn get [&rest args] 42)")
|
cant_compile("(defn get [&rest args] 42)")
|
||||||
|
can_compile("(defclass A [] (defn get [self] 42))")
|
||||||
|
can_compile("""
|
||||||
|
(defclass A []
|
||||||
|
(defn get [self] 42)
|
||||||
|
(defclass B []
|
||||||
|
(defn get [self] 42))
|
||||||
|
(defn if [self] 0))
|
||||||
|
""")
|
||||||
|
Loading…
Reference in New Issue
Block a user