Commit 4dbce65d authored by Stefan Behnel's avatar Stefan Behnel

Clean up and repair the type spec generation for the limited API, leaving more...

Clean up and repair the type spec generation for the limited API, leaving more of the work to the TypeSlots instead of special-casing all sorts of things.
parent bc40c5f4
...@@ -2231,45 +2231,23 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2231,45 +2231,23 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_typeobj_spec(self, modname, entry, code): def generate_typeobj_spec(self, modname, entry, code):
type = entry.type type = entry.type
scope = type.scope scope = type.scope
code.putln("static PyType_Slot %s_slots[] = {" % type.typeobj_cname)
for slot in TypeSlots.slot_table:
slot.generate_spec(scope, code)
code.putln("{0, 0},")
code.putln("};")
if type.typedef_flag: if type.typedef_flag:
objstruct = type.objstruct_cname objstruct = type.objstruct_cname
else: else:
objstruct = "struct %s" % type.objstruct_cname objstruct = "struct %s" % type.objstruct_cname
classname = scope.class_name.as_c_string_literal() classname = scope.class_name.as_c_string_literal()
code.putln("static PyType_Slot %s_slots[] = {" % type.typeobj_cname)
has_tp_getattro = False
for slot in TypeSlots.slot_table:
if slot.slot_name == "tp_flags":
continue
if slot.slot_name == "tp_dealloc" and scope.lookup_here("__dealloc__") is None:
continue
if slot.slot_name == "tp_getattro":
has_tp_getattro = True
if slot.slot_name == "tp_as_number":
slot.generate_substructure_spec(scope, code)
continue
if slot.slot_name == "tp_as_sequence":
slot.generate_substructure_spec(scope, code)
continue
if slot.slot_name == "tp_as_mapping":
slot.generate_substructure_spec(scope, code)
continue
if slot.slot_name == "tp_as_buffer": # Can't support tp_as_buffer
continue
v = TypeSlots.get_slot_by_name(slot.slot_name).spec_slot_value(scope)
if v is not None:
code.putln(" {Py_%s, (void *)%s}," % (slot.slot_name, v))
if not has_tp_getattro:
code.putln(" {Py_tp_getattro, __Pyx_PyObject_GenericGetAttr},")
code.putln(" {0, 0},")
code.putln("};")
code.putln("static PyType_Spec %s_spec = {" % type.typeobj_cname) code.putln("static PyType_Spec %s_spec = {" % type.typeobj_cname)
code.putln(" \"%s.%s\"," % (self.full_module_name, classname.replace("\"", ""))) code.putln('"%s.%s",' % (self.full_module_name, classname.replace('"', '')))
code.putln(" sizeof(%s)," % objstruct) code.putln("sizeof(%s)," % objstruct)
code.putln(" 0,") code.putln("0,")
code.putln(" %s," % TypeSlots.get_slot_by_name("tp_flags").spec_slot_value(scope)) code.putln("%s," % TypeSlots.get_slot_by_name("tp_flags").slot_code(scope))
code.putln(" %s_slots," % type.typeobj_cname) code.putln("%s_slots," % type.typeobj_cname)
code.putln("};") code.putln("};")
def generate_typeobj_definition(self, modname, entry, code): def generate_typeobj_definition(self, modname, entry, code):
......
...@@ -229,6 +229,12 @@ class SlotDescriptor(object): ...@@ -229,6 +229,12 @@ class SlotDescriptor(object):
self.py3 = py3 self.py3 = py3
self.py2 = py2 self.py2 = py2
def slot_code(self, scope):
raise NotImplemented()
def spec_value(self, scope):
return self.slot_code(scope)
def preprocessor_guard_code(self): def preprocessor_guard_code(self):
ifdef = self.ifdef ifdef = self.ifdef
py2 = self.py2 py2 = self.py2
...@@ -242,15 +248,20 @@ class SlotDescriptor(object): ...@@ -242,15 +248,20 @@ class SlotDescriptor(object):
guard = ("#if PY_MAJOR_VERSION >= 3") guard = ("#if PY_MAJOR_VERSION >= 3")
return guard return guard
def spec_slot_value(self, scope): def generate_spec(self, scope, code):
if self.is_initialised_dynamically: if self.is_initialised_dynamically:
return None return
result = self.slot_code(scope) value = self.spec_value(scope)
if result == "0": if value == "0":
return None return
return result preprocessor_guard = self.preprocessor_guard_code()
if preprocessor_guard:
code.putln(preprocessor_guard)
code.putln("{Py_%s, (void *)%s}," % (self.slot_name, value))
if preprocessor_guard:
code.putln("#endif")
def generate(self, scope, code, spec=False): def generate(self, scope, code):
preprocessor_guard = self.preprocessor_guard_code() preprocessor_guard = self.preprocessor_guard_code()
if preprocessor_guard: if preprocessor_guard:
code.putln(preprocessor_guard) code.putln(preprocessor_guard)
...@@ -279,11 +290,7 @@ class SlotDescriptor(object): ...@@ -279,11 +290,7 @@ class SlotDescriptor(object):
code.putln("#else") code.putln("#else")
end_pypy_guard = True end_pypy_guard = True
if spec: code.putln("%s, /*%s*/" % (value, self.slot_name))
if value != "0":
code.putln("{Py_%s, (void *)%s}," % (self.slot_name, value))
else:
code.putln("%s, /*%s*/" % (value, self.slot_name))
if end_pypy_guard: if end_pypy_guard:
code.putln("#endif") code.putln("#endif")
...@@ -449,6 +456,11 @@ class ConstructorSlot(InternalMethodSlot): ...@@ -449,6 +456,11 @@ class ConstructorSlot(InternalMethodSlot):
return slot_code or '0' return slot_code or '0'
return InternalMethodSlot.slot_code(self, scope) return InternalMethodSlot.slot_code(self, scope)
def spec_value(self, scope):
if self.slot_name == "tp_dealloc" and not scope.lookup_here("__dealloc__"):
return "0"
return self.slot_code(scope)
def generate_dynamic_init_code(self, scope, code): def generate_dynamic_init_code(self, scope, code):
if self.slot_code(scope) != '0': if self.slot_code(scope) != '0':
return return
...@@ -484,6 +496,11 @@ class SyntheticSlot(InternalMethodSlot): ...@@ -484,6 +496,11 @@ class SyntheticSlot(InternalMethodSlot):
else: else:
return self.default_value return self.default_value
def spec_value(self, scope):
if self.slot_name == "tp_getattro" and not scope.defines_any_special(self.user_methods):
return "__Pyx_PyObject_GenericGetAttr"
return self.slot_code(scope)
class RichcmpSlot(MethodSlot): class RichcmpSlot(MethodSlot):
def slot_code(self, scope): def slot_code(self, scope):
...@@ -514,6 +531,10 @@ class TypeFlagsSlot(SlotDescriptor): ...@@ -514,6 +531,10 @@ class TypeFlagsSlot(SlotDescriptor):
value += "|Py_TPFLAGS_HAVE_GC" value += "|Py_TPFLAGS_HAVE_GC"
return value return value
def generate_spec(self, scope, code):
# Flags are stored in the PyType_Spec, not in a PyType_Slot.
return
class DocStringSlot(SlotDescriptor): class DocStringSlot(SlotDescriptor):
# Descriptor for the docstring slot. # Descriptor for the docstring slot.
...@@ -567,10 +588,12 @@ class SuiteSlot(SlotDescriptor): ...@@ -567,10 +588,12 @@ class SuiteSlot(SlotDescriptor):
if self.ifdef: if self.ifdef:
code.putln("#endif") code.putln("#endif")
def generate_substructure_spec(self, scope, code): def generate_spec(self, scope, code):
if not self.is_empty(scope): if self.slot_name == "tp_as_buffer":
for slot in self.sub_slots: # Cannot currently support the buffer protocol in the limited C-API.
slot.generate(scope, code, spec=True) return
for slot in self.sub_slots:
slot.generate_spec(scope, code)
substructures = [] # List of all SuiteSlot instances substructures = [] # List of all SuiteSlot instances
......
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