summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2020-04-26 20:28:56 +0200
committerStefan Behnel <stefan_ml@behnel.de>2020-04-26 20:28:56 +0200
commit4dbce65d359473c1dc37eb0c325ae177aa0774a2 (patch)
tree32c331cf02c822b5c3a9824595d9a5555d11162d
parentbc40c5f4873ad41a63de64c94331c45f0def148d (diff)
downloadcython-4dbce65d359473c1dc37eb0c325ae177aa0774a2.tar.gz
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.
-rw-r--r--Cython/Compiler/ModuleNode.py44
-rw-r--r--Cython/Compiler/TypeSlots.py55
2 files changed, 50 insertions, 49 deletions
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index 1be6e7f27..51458036d 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -2231,45 +2231,23 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_typeobj_spec(self, modname, entry, code):
type = entry.type
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:
objstruct = type.objstruct_cname
else:
objstruct = "struct %s" % type.objstruct_cname
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(" \"%s.%s\"," % (self.full_module_name, classname.replace("\"", "")))
- code.putln(" sizeof(%s)," % objstruct)
- code.putln(" 0,")
- code.putln(" %s," % TypeSlots.get_slot_by_name("tp_flags").spec_slot_value(scope))
- code.putln(" %s_slots," % type.typeobj_cname)
+ code.putln('"%s.%s",' % (self.full_module_name, classname.replace('"', '')))
+ code.putln("sizeof(%s)," % objstruct)
+ code.putln("0,")
+ code.putln("%s," % TypeSlots.get_slot_by_name("tp_flags").slot_code(scope))
+ code.putln("%s_slots," % type.typeobj_cname)
code.putln("};")
def generate_typeobj_definition(self, modname, entry, code):
diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py
index 5ff5d8e3c..4236e8ec6 100644
--- a/Cython/Compiler/TypeSlots.py
+++ b/Cython/Compiler/TypeSlots.py
@@ -229,6 +229,12 @@ class SlotDescriptor(object):
self.py3 = py3
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):
ifdef = self.ifdef
py2 = self.py2
@@ -242,15 +248,20 @@ class SlotDescriptor(object):
guard = ("#if PY_MAJOR_VERSION >= 3")
return guard
- def spec_slot_value(self, scope):
+ def generate_spec(self, scope, code):
if self.is_initialised_dynamically:
- return None
- result = self.slot_code(scope)
- if result == "0":
- return None
- return result
+ return
+ value = self.spec_value(scope)
+ if value == "0":
+ return
+ 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()
if preprocessor_guard:
code.putln(preprocessor_guard)
@@ -279,11 +290,7 @@ class SlotDescriptor(object):
code.putln("#else")
end_pypy_guard = True
- if spec:
- if value != "0":
- code.putln("{Py_%s, (void *)%s}," % (self.slot_name, value))
- else:
- code.putln("%s, /*%s*/" % (value, self.slot_name))
+ code.putln("%s, /*%s*/" % (value, self.slot_name))
if end_pypy_guard:
code.putln("#endif")
@@ -449,6 +456,11 @@ class ConstructorSlot(InternalMethodSlot):
return slot_code or '0'
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):
if self.slot_code(scope) != '0':
return
@@ -484,6 +496,11 @@ class SyntheticSlot(InternalMethodSlot):
else:
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):
def slot_code(self, scope):
@@ -514,6 +531,10 @@ class TypeFlagsSlot(SlotDescriptor):
value += "|Py_TPFLAGS_HAVE_GC"
return value
+ def generate_spec(self, scope, code):
+ # Flags are stored in the PyType_Spec, not in a PyType_Slot.
+ return
+
class DocStringSlot(SlotDescriptor):
# Descriptor for the docstring slot.
@@ -567,10 +588,12 @@ class SuiteSlot(SlotDescriptor):
if self.ifdef:
code.putln("#endif")
- def generate_substructure_spec(self, scope, code):
- if not self.is_empty(scope):
- for slot in self.sub_slots:
- slot.generate(scope, code, spec=True)
+ def generate_spec(self, scope, code):
+ if self.slot_name == "tp_as_buffer":
+ # Cannot currently support the buffer protocol in the limited C-API.
+ return
+ for slot in self.sub_slots:
+ slot.generate_spec(scope, code)
substructures = [] # List of all SuiteSlot instances