Commit 014fed72 authored by Xavier Thompson's avatar Xavier Thompson

Support wrapping cypclass with multiple bases

parent 7ecbe620
......@@ -154,10 +154,7 @@ class CypclassWrapperInjection(VisitorTransform):
if not node_has_suite:
return None
if len(node.base_classes) > 1:
return None
# TODO: take nesting into account for the name
cclass_name = EncodedString("%s_cyp_wrapper" % node.name)
......@@ -217,13 +214,12 @@ class CypclassWrapperInjection(VisitorTransform):
return wrapper
def synthesize_underlying_cyobject_attribute(self, node):
nested_names = [node.name for node in self.nesting_stack]
underlying_base_type = Nodes.CSimpleBaseTypeNode(
void_type_node = Nodes.CSimpleBaseTypeNode(
node.pos,
name = node.name,
module_path = nested_names,
is_basic_c_type = 0,
name = "void",
module_path = [],
is_basic_c_type = 1,
signed = 1,
complex = 0,
longness = 0,
......@@ -232,11 +228,12 @@ class CypclassWrapperInjection(VisitorTransform):
)
underlying_name_declarator = Nodes.CNameDeclaratorNode(node.pos, name=underlying_name, cname=None)
underlying_name_declarator = Nodes.CPtrDeclaratorNode(node.pos, base=underlying_name_declarator)
underlying_cyobject = Nodes.CVarDefNode(
pos = node.pos,
visibility = 'private',
base_type = underlying_base_type,
base_type = void_type_node,
declarators = [underlying_name_declarator],
in_pxd = node.in_pxd,
doc = None,
......
......@@ -1684,10 +1684,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"static void %s(PyObject *o) {" % slot_func_cname)
# for cyp wrappers, just decrement the atomic counter of the underlying type
is_cyp_wrapper = scope.parent_type.is_cyp_wrapper
if is_cyp_wrapper:
parent_type = scope.parent_type
if parent_type.is_cyp_wrapper:
underlying_type_decl = parent_type.wrapped_decl
underlying_attribute_name = CypclassWrapper.underlying_name
self.generate_self_cast(scope, code)
code.putln("Cy_DECREF(p->%s);" % CypclassWrapper.underlying_name)
code.putln(
"%s * p_nogil_cyobject = (%s *) (p->%s);"
% (underlying_type_decl, underlying_type_decl, underlying_attribute_name)
)
code.putln("Cy_DECREF(p_nogil_cyobject);")
code.putln("}")
if cdealloc_func_entry is None:
code.putln("#endif")
......
......@@ -5570,6 +5570,8 @@ class CypclassWrapperDefNode(CClassDefNode):
self.entry.type.is_cyp_wrapper = 1
# > associate the wrapper type to the wrapped type
self.wrapped_cypclass.entry.type.wrapper_type = self.entry.type
# > remember the cname of the wrapped type
self.entry.type.wrapped_decl = self.wrapped_cypclass.entry.type.empty_declaration_code()
# > insert and analyse each method wrapper
self.insert_cypclass_method_wrappers(env)
......@@ -5650,16 +5652,20 @@ class CypclassWrapperDefNode(CClassDefNode):
# > reference to the self argument of the wrapper method
self_obj = ExprNodes.NameNode(self_pos, name=self_name)
# > access the method of the underlying cyobject from the self argument of the wrapper method
# > access the underlying cyobject from the self argument of the wrapper method
underlying_obj = ExprNodes.AttributeNode(cfunc_method.pos, obj=self_obj, attribute=underlying_name)
empty_declarator = CNameDeclaratorNode(cfunc_method.pos, name="", cname=None)
cast_underlying_obj = ExprNodes.TypecastNode(
cast_operation = ExprNodes.TypecastNode(
cfunc_method.pos,
type = self.wrapped_cypclass.entry.type,
operand = underlying_obj,
typecheck = False
)
cast_underlying_obj = ExprNodes.NameNode(self_pos, name=EncodedString("cast_cyobject"))
cast_assignment = SingleAssignmentNode(self_pos, lhs=cast_underlying_obj, rhs=cast_operation)
# > access the method of the underlying object
cfunc = ExprNodes.AttributeNode(cfunc_method.pos, obj=cast_underlying_obj, attribute=cfunc_name)
# > call to the underlying method
......@@ -5674,7 +5680,7 @@ class CypclassWrapperDefNode(CClassDefNode):
py_stat = ExprStatNode(cfunc_method.pos, expr=c_call)
else:
py_stat = ReturnStatNode(cfunc_method.pos, return_type=PyrexTypes.py_object_type, value=c_call)
py_body = StatListNode(cfunc_method.pos, stats=[py_stat])
py_body = StatListNode(cfunc_method.pos, stats=[cast_assignment, py_stat])
# > lock around the call in checklock mode
if self.wrapped_cypclass.lock_mode == 'checklock':
......@@ -5682,7 +5688,7 @@ class CypclassWrapperDefNode(CClassDefNode):
lock_node = LockCypclassNode(
cfunc_method.pos,
state = 'wlocked' if need_wlock else 'rlocked',
obj = underlying_obj,
obj = cast_underlying_obj,
body = py_body
)
py_body = lock_node
......
......@@ -1499,11 +1499,13 @@ class PyExtensionType(PyObjectType):
# defered_declarations [thunk] Used to declare class hierarchies in order
# check_size 'warn', 'error', 'ignore' What to do if tp_basicsize does not match
# is_cyp_wrapper boolean Whether this extension type wraps a cypclass
# wrapped_decl string or None The declaration code of the wrapped cypclass type when this is a cyp_wrapper
is_extension_type = 1
has_attributes = 1
early_init = 1
is_cyp_wrapper = 0
wrapped_decl = None
objtypedef_cname = 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