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):
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):
......
......@@ -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
......
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