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

Support wrapping cypclass with multiple bases

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