Commit d881105c authored by Stefan Behnel's avatar Stefan Behnel

Mark "__eq__" and friends as special methods to correctly distinguish them from attributes etc.

Replace closure class special casing from slot generation code and replace it with saner and more general "is_special" check.
parent c062260b
...@@ -1200,33 +1200,31 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1200,33 +1200,31 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_traverse_function(scope, code, entry) self.generate_traverse_function(scope, code, entry)
if scope.needs_tp_clear(): if scope.needs_tp_clear():
self.generate_clear_function(scope, code, entry) self.generate_clear_function(scope, code, entry)
if not scope.is_closure_class_scope: if scope.defines_any_special(["__getitem__"]):
# in closure classes, these are user defined variable names self.generate_getitem_int_function(scope, code)
if scope.defines_any(["__getitem__"]): if scope.defines_any_special(["__setitem__", "__delitem__"]):
self.generate_getitem_int_function(scope, code) self.generate_ass_subscript_function(scope, code)
if scope.defines_any(["__setitem__", "__delitem__"]): if scope.defines_any_special(["__getslice__", "__setslice__", "__delslice__"]):
self.generate_ass_subscript_function(scope, code) warning(self.pos,
if scope.defines_any(["__getslice__", "__setslice__", "__delslice__"]): "__getslice__, __setslice__, and __delslice__ are not supported by Python 3, "
warning(self.pos, "use __getitem__, __setitem__, and __delitem__ instead", 1)
"__getslice__, __setslice__, and __delslice__ are not supported by Python 3, " code.putln("#if PY_MAJOR_VERSION >= 3")
"use __getitem__, __setitem__, and __delitem__ instead", 1) code.putln("#error __getslice__, __setslice__, and __delslice__ not supported in Python 3.")
code.putln("#if PY_MAJOR_VERSION >= 3") code.putln("#endif")
code.putln("#error __getslice__, __setslice__, and __delslice__ not supported in Python 3.") if scope.defines_any_special(["__setslice__", "__delslice__"]):
code.putln("#endif") self.generate_ass_slice_function(scope, code)
if scope.defines_any(["__setslice__", "__delslice__"]): if scope.defines_any_special(["__getattr__", "__getattribute__"]):
self.generate_ass_slice_function(scope, code) self.generate_getattro_function(scope, code)
if scope.defines_any(["__getattr__", "__getattribute__"]): if scope.defines_any_special(["__setattr__", "__delattr__"]):
self.generate_getattro_function(scope, code) self.generate_setattro_function(scope, code)
if scope.defines_any(["__setattr__", "__delattr__"]): if scope.defines_any_special(["__get__"]):
self.generate_setattro_function(scope, code) self.generate_descr_get_function(scope, code)
if scope.defines_any(["__get__"]): if scope.defines_any_special(["__set__", "__delete__"]):
self.generate_descr_get_function(scope, code) self.generate_descr_set_function(scope, code)
if scope.defines_any(["__set__", "__delete__"]): if not scope.is_closure_class_scope and scope.defines_any(["__dict__"]):
self.generate_descr_set_function(scope, code) self.generate_dict_getter_function(scope, code)
if scope.defines_any(["__dict__"]): if scope.defines_any_special(TypeSlots.richcmp_special_methods):
self.generate_dict_getter_function(scope, code) self.generate_richcmp_function(scope, code)
if scope.defines_any(TypeSlots.richcmp_special_methods):
self.generate_richcmp_function(scope, code)
self.generate_property_accessors(scope, code) self.generate_property_accessors(scope, code)
self.generate_method_table(scope, code) self.generate_method_table(scope, code)
self.generate_getset_table(scope, code) self.generate_getset_table(scope, code)
......
...@@ -892,13 +892,19 @@ class Scope(object): ...@@ -892,13 +892,19 @@ class Scope(object):
pass pass
def defines_any(self, names): def defines_any(self, names):
# Test whether any of the given names are # Test whether any of the given names are defined in this scope.
# defined in this scope.
for name in names: for name in names:
if name in self.entries: if name in self.entries:
return 1 return 1
return 0 return 0
def defines_any_special(self, names):
# Test whether any of the given names are defined as special methods in this scope.
for name in names:
if name in self.entries and self.entries[name].is_special:
return 1
return 0
def infer_types(self): def infer_types(self):
from .TypeInference import get_type_inferer from .TypeInference import get_type_inferer
get_type_inferer().infer_types(self) get_type_inferer().infer_types(self)
......
...@@ -304,14 +304,12 @@ class MethodSlot(SlotDescriptor): ...@@ -304,14 +304,12 @@ class MethodSlot(SlotDescriptor):
method_name_to_slot[method_name] = self method_name_to_slot[method_name] = self
def slot_code(self, scope): def slot_code(self, scope):
if scope.is_closure_class_scope:
return "0"
entry = scope.lookup_here(self.method_name) entry = scope.lookup_here(self.method_name)
if entry and entry.func_cname: if entry and entry.is_special and entry.func_cname:
return entry.func_cname return entry.func_cname
for method_name in self.alternatives: for method_name in self.alternatives:
entry = scope.lookup_here(method_name) entry = scope.lookup_here(method_name)
if entry and entry.func_cname: if entry and entry.is_special and entry.func_cname:
return entry.func_cname return entry.func_cname
return "0" return "0"
...@@ -367,14 +365,13 @@ class ConstructorSlot(InternalMethodSlot): ...@@ -367,14 +365,13 @@ class ConstructorSlot(InternalMethodSlot):
self.method = method self.method = method
def slot_code(self, scope): def slot_code(self, scope):
if scope.is_closure_class_scope: entry = scope.lookup_here(self.method)
return "0"
if (self.slot_name != 'tp_new' if (self.slot_name != 'tp_new'
and scope.parent_type.base_type and scope.parent_type.base_type
and not scope.has_pyobject_attrs and not scope.has_pyobject_attrs
and not scope.has_memoryview_attrs and not scope.has_memoryview_attrs
and not scope.has_cpp_class_attrs and not scope.has_cpp_class_attrs
and not scope.lookup_here(self.method)): and not (entry and entry.is_special)):
# if the type does not have object attributes, it can # if the type does not have object attributes, it can
# delegate GC methods to its parent - iff the parent # delegate GC methods to its parent - iff the parent
# functions are defined in the same module # functions are defined in the same module
...@@ -383,6 +380,8 @@ class ConstructorSlot(InternalMethodSlot): ...@@ -383,6 +380,8 @@ class ConstructorSlot(InternalMethodSlot):
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
if entry.visibility != 'extern': if entry.visibility != 'extern':
return self.slot_code(parent_type_scope) return self.slot_code(parent_type_scope)
if entry and not entry.is_special:
return "0"
return InternalMethodSlot.slot_code(self, scope) return InternalMethodSlot.slot_code(self, scope)
...@@ -400,9 +399,7 @@ class SyntheticSlot(InternalMethodSlot): ...@@ -400,9 +399,7 @@ class SyntheticSlot(InternalMethodSlot):
self.default_value = default_value self.default_value = default_value
def slot_code(self, scope): def slot_code(self, scope):
if scope.is_closure_class_scope: if scope.defines_any_special(self.user_methods):
return "0"
if scope.defines_any(self.user_methods):
return InternalMethodSlot.slot_code(self, scope) return InternalMethodSlot.slot_code(self, scope)
else: else:
return self.default_value return self.default_value
...@@ -410,12 +407,10 @@ class SyntheticSlot(InternalMethodSlot): ...@@ -410,12 +407,10 @@ class SyntheticSlot(InternalMethodSlot):
class RichcmpSlot(MethodSlot): class RichcmpSlot(MethodSlot):
def slot_code(self, scope): def slot_code(self, scope):
if scope.is_closure_class_scope:
return "0"
entry = scope.lookup_here(self.method_name) entry = scope.lookup_here(self.method_name)
if entry and entry.func_cname: if entry and entry.is_special and entry.func_cname:
return entry.func_cname return entry.func_cname
elif scope.defines_any(richcmp_special_methods): elif scope.defines_any_special(richcmp_special_methods):
return scope.mangle_internal(self.slot_name) return scope.mangle_internal(self.slot_name)
else: else:
return "0" return "0"
...@@ -464,8 +459,6 @@ class SuiteSlot(SlotDescriptor): ...@@ -464,8 +459,6 @@ class SuiteSlot(SlotDescriptor):
substructures.append(self) substructures.append(self)
def is_empty(self, scope): def is_empty(self, scope):
if scope.is_closure_class_scope:
return True
for slot in self.sub_slots: for slot in self.sub_slots:
if slot.slot_code(scope) != "0": if slot.slot_code(scope) != "0":
return False return False
...@@ -582,6 +575,8 @@ def get_special_method_signature(name): ...@@ -582,6 +575,8 @@ def get_special_method_signature(name):
slot = method_name_to_slot.get(name) slot = method_name_to_slot.get(name)
if slot: if slot:
return slot.signature return slot.signature
elif name in richcmp_special_methods:
return binaryfunc
else: else:
return None return None
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment