type.declaration_code("")))
def generate_new_function(self, scope, code):
+ tp_slot = TypeSlots.ConstructorSlot("tp_new", '__new__')
+ slot_func = scope.mangle_internal("tp_new")
+ if tp_slot.slot_code(scope) != slot_func:
+ return # never used
type = scope.parent_type
base_type = type.base_type
py_attrs = []
"%s;"
% scope.parent_type.declaration_code("p"))
if base_type:
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
+ if scope.parent_scope is base_type.scope.parent_scope and entry.visibility != 'extern':
+ tp_new = TypeSlots.InternalMethodSlot("tp_new").slot_code(base_type.scope)
+ else:
+ tp_new = "%s->tp_new" % base_type.typeptr_cname
code.putln(
- "PyObject *o = %s->tp_new(t, a, k);" %
- base_type.typeptr_cname)
+ "PyObject *o = %s(t, a, k);" % tp_new)
else:
code.putln(
"PyObject *o = (*t->tp_alloc)(t, 0);")
"}")
def generate_dealloc_function(self, scope, code):
+ tp_slot = TypeSlots.ConstructorSlot("tp_dealloc", '__dealloc__')
+ slot_func = scope.mangle_internal("tp_dealloc")
base_type = scope.parent_type.base_type
+ if tp_slot.slot_code(scope) != slot_func:
+ return # never used
code.putln("")
code.putln(
"static void %s(PyObject *o) {"
for entry in py_attrs:
code.put_xdecref("p->%s" % entry.cname, entry.type)
if base_type:
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
+ if scope.parent_scope is base_type.scope.parent_scope and entry.visibility != 'extern':
+ tp_dealloc = TypeSlots.InternalMethodSlot("tp_dealloc").slot_code(base_type.scope)
+ else:
+ tp_dealloc = "%s->tp_dealloc" % base_type.typeptr_cname
code.putln(
- "%s->tp_dealloc(o);" %
- base_type.typeptr_cname)
+ "%s(o);" % tp_dealloc)
else:
code.putln(
- "(*o->ob_type->tp_free)(o);")
+ "(*o->ob_type->tp_free)(o);")
code.putln(
"}")
if base_type:
# want to call it explicitly if possible so inlining can be performed
parent_slot = tp_slot.slot_code(base_type.scope)
- if scope.parent_scope is base_type.scope.parent_scope and parent_slot != '0':
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
+ if scope.parent_scope is base_type.scope.parent_scope and parent_slot != '0' and entry.visibility != 'extern':
code.putln("e = %s(o, v, a); if (e) return e;" % parent_slot)
else:
code.putln("if (%s->tp_traverse) {" % base_type.typeptr_cname)
if base_type:
# want to call it explicitly if possible so inlining can be performed
parent_slot = tp_slot.slot_code(base_type.scope)
- if scope.parent_scope is base_type.scope.parent_scope and parent_slot != '0':
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
+ if scope.parent_scope is base_type.scope.parent_scope and parent_slot != '0' and entry.visibility != 'extern':
code.putln("%s(o);" % parent_slot)
else:
code.putln("if (%s->tp_clear) {" % base_type.typeptr_cname)
# functions are defined in the same module
parent_type_scope = scope.parent_type.base_type.scope
if scope.parent_scope is parent_type_scope.parent_scope:
- return self.slot_code(parent_type_scope)
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
+ if entry.visibility != 'extern':
+ return self.slot_code(parent_type_scope)
+ return InternalMethodSlot.slot_code(self, scope)
+
+
+class ConstructorSlot(InternalMethodSlot):
+ # Descriptor for tp_new and tp_dealloc.
+
+ def __init__(self, slot_name, method):
+ InternalMethodSlot.__init__(self, slot_name)
+ self.method = method
+
+ def slot_code(self, scope):
+ if scope.parent_type.base_type \
+ and not scope.has_pyobject_attrs \
+ and not scope.lookup_here(self.method):
+ # if the type does not have object attributes, it can
+ # delegate GC methods to its parent - iff the parent
+ # functions are defined in the same module
+ parent_type_scope = scope.parent_type.base_type.scope
+ if scope.parent_scope is parent_type_scope.parent_scope:
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
+ if entry.visibility != 'extern':
+ return self.slot_code(parent_type_scope)
return InternalMethodSlot.slot_code(self, scope)
#------------------------------------------------------------------------------------------
slot_table = (
- InternalMethodSlot("tp_dealloc"),
+ ConstructorSlot("tp_dealloc", '__dealloc__'),
EmptySlot("tp_print"), #MethodSlot(printfunc, "tp_print", "__print__"),
EmptySlot("tp_getattr"),
EmptySlot("tp_setattr"),
MethodSlot(initproc, "tp_init", "__init__"),
EmptySlot("tp_alloc"), #FixedSlot("tp_alloc", "PyType_GenericAlloc"),
- InternalMethodSlot("tp_new"),
+ ConstructorSlot("tp_new", '__new__'),
EmptySlot("tp_free"),
EmptySlot("tp_is_gc"),