Commit dd1c4c74 authored by gsamain's avatar gsamain

Cypclass constructor wrapper

parent a845670d
......@@ -5503,14 +5503,39 @@ class CallNode(ExprNode):
elif type and type.is_cpp_class:
self.args = [ arg.analyse_types(env) for arg in self.args ]
constructor = type.scope.lookup("<init>")
if not constructor:
constructor_type = None
constructor_cname = None
if type.is_cyp_class:
constructor = wrapper = type.scope.lookup_here("<constructor>")
if not wrapper:
error(self.function.pos, "no constructor wrapper found for Cypclass type '%s'" % self.function.name)
namespace_list = wrapper.func_cname.split('::')
templates = ''
if type.templates:
templates = '<' + ','.join([param.declaration_code('')
for param in type.templates
if not PyrexTypes.is_optional_template_param(param) and not param.is_fused]) + '>'
if len(namespace_list) > 2:
# We do this because cypclass wrappers are outside of the class namespace
# in the C++ code, but they are declared within the class scope
constructor_cname = '::'.join(namespace_list[:-2] + [namespace_list[-1]]) + templates
else:
constructor_cname = namespace_list[-1] + templates
constructor_type = wrapper.type
elif not constructor:
error(self.function.pos, "no constructor found for C++ type '%s'" % self.function.name)
self.type = error_type
return self
self.function = RawCNameExprNode(self.function.pos, constructor.type)
else:
constructor_type = constructor.type
constructor_cname = type.empty_declaration_code()
self.function = RawCNameExprNode(self.function.pos, constructor_type)
self.function.entry = constructor
self.function.set_cname(type.empty_declaration_code())
self.function.set_cname(constructor_cname)
self.analyse_c_function_call(env)
if type.is_cyp_class:
self.type = constructor_type.return_type
else:
self.type = type
return True
......
This diff is collapsed.
......@@ -653,7 +653,28 @@ class Scope(object):
if scope:
entry.type.set_scope(scope)
declare_inherited_attributes(entry, base_classes)
scope.declare_var(name="this", cname="this", type=PyrexTypes.CPtrType(entry.type), pos=entry.pos)
this_type = PyrexTypes.CPtrType(entry.type) if not cypclass else entry.type
scope.declare_var(name="this", cname="this", type=this_type, pos=entry.pos)
if cypclass:
# Declare a shadow default constructor
wrapper_type = PyrexTypes.CFuncType(entry.type, [], nogil=1)
wrapper_cname = "%s__constructor__%s" % (Naming.func_prefix, name)
wrapper_name = "<constructor>"
wrapper_entry = scope.declare(wrapper_name, wrapper_cname, wrapper_type, pos, visibility)
wrapper_type.entry = wrapper_entry
wrapper_entry.is_inherited = 1
wrapper_entry.is_cfunction = 1
wrapper_entry.func_cname = "%s::%s" % (entry.type.empty_declaration_code(), wrapper_cname)
# Declare the default __alloc__ method
alloc_type = wrapper_type
alloc_cname = "%s__alloc__%s" % (Naming.func_prefix, name)
alloc_name = "<alloc>"
alloc_entry = scope.declare(alloc_name, alloc_cname, alloc_type, pos, visibility)
alloc_type.entry = alloc_entry
alloc_entry.is_cfunction = 1
alloc_entry.func_cname = "%s::%s" % (entry.type.empty_declaration_code(), alloc_cname)
if self.is_cpp_class_scope:
entry.type.namespace = self.outer_scope.lookup(self.name).type
return entry
......@@ -2445,6 +2466,26 @@ class CppClassScope(Scope):
self.var_entries.append(entry)
return entry
def declare_constructor_wrapper(self, args, pos, defining=0, has_varargs=0, optional_arg_count=0, op_arg_struct = None, return_type=None):
if not return_type:
return_type = self.type
class_type = self.parent_type
class_name = self.name.split('::')[-1]
wrapper_cname = "%s__constructor__%s" % (Naming.func_prefix, class_name)
wrapper_name = "<constructor>"
wrapper_type = PyrexTypes.CFuncType(return_type, args, nogil=1,
has_varargs=has_varargs,
optional_arg_count=optional_arg_count)
if op_arg_struct:
wrapper_type.op_arg_struct = op_arg_struct
wrapper_entry = self.declare(wrapper_name, wrapper_cname, wrapper_type,
pos, 'extern')
wrapper_type.entry = wrapper_entry
wrapper_entry.is_cfunction = 1
if defining:
wrapper_entry.func_cname = "%s::%s" % (class_type.empty_declaration_code(), wrapper_cname)
return wrapper_entry
def declare_cfunction(self, name, type, pos,
cname=None, visibility='extern', api=0, in_pxd=0,
defining=0, modifiers=(), utility_code=None, overridable=False):
......@@ -2457,16 +2498,40 @@ class CppClassScope(Scope):
# arguments that cannot by called by value.
type.original_args = type.args
def maybe_ref(arg):
if arg.type.is_cpp_class and not arg.type.is_reference:
if arg.type.is_cpp_class and not arg.type.is_reference and not arg.type.is_cyp_class:
return PyrexTypes.CFuncTypeArg(
arg.name, PyrexTypes.c_ref_type(arg.type), arg.pos)
else:
return arg
type.args = [maybe_ref(arg) for arg in type.args]
if self.type.is_cyp_class and not self.lookup_here("__new__"):
self.declare_constructor_wrapper(type.args, pos, defining,
type.has_varargs, type.optional_arg_count,
getattr(type, 'op_arg_struct', None))
elif name == '__dealloc__' and cname is None:
cname = "%s__dealloc__%s" % (Naming.func_prefix, class_name)
name = '<del>'
type.return_type = PyrexTypes.c_void_type
elif name == '__alloc__' and self.type.is_cyp_class:
cname = "%s__alloc__%s" % (Naming.func_prefix, class_name)
name = '<alloc>'
elif name == '__new__' and self.type.is_cyp_class:
if name in self.entries:
if self.entries[name].is_inherited:
del self.entries[name]
else:
error(pos, "Couldn't have more than one __new__ function")
if self.lookup_here("<constructor>"):
del self.entries["<constructor>"]
self.declare_constructor_wrapper(type.args[1:], pos, defining,
type.has_varargs, type.optional_arg_count,
getattr(type, 'op_arg_struct', None),
return_type=type.return_type)
type.original_alloc_type = type.args[0]
if name in ('<init>', '<del>') and type.nogil:
for base in self.type.base_classes:
if base is cy_object_type:
......@@ -2501,9 +2566,44 @@ class CppClassScope(Scope):
for base_entry in \
base_scope.inherited_var_entries + base_scope.var_entries:
#constructor/destructor is not inherited
if base_entry.name in ("<init>", "<del>"):
if base_entry.name == "<del>"\
or base_entry.name == "<init>" and not self.parent_type.is_cyp_class\
or base_entry.name in ("<constructor>", "<alloc>") and self.parent_type.is_cyp_class:
continue
elif base_entry.name == "<init>" and not self.lookup_here("__new__"):
wrapper_entry = self.declare_constructor_wrapper(base_entry_type.args, base_entry.pos,
defining=1, has_varargs = base_entry_type.has_varargs,
optional_arg_count = base_entry_type.optional_arg_count,
op_arg_struct = getattr(base_entry_type, 'op_arg_struct', None),
return_type=self.parent_type)
wrapper_entry.is_inherited = 1
#print base_entry.name, self.entries
elif base_entry.name == "__new__" and self.parent_type.is_cyp_class:
# Rewrite first argument for __new__
alloc_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(
self.parent_type, [], nogil=1))
alloc_arg = PyrexTypes.CFuncTypeArg(base_entry.type.args[0].name, alloc_type,
base_entry.type.args[0].pos, cname=base_entry.type.args[0].cname)
base_entry_type = PyrexTypes.CFuncType(base_entry_type.return_type,
[alloc_arg] + base_entry_type.args[1:], nogil=1,
has_varargs=base_entry_type.has_varargs,
optional_arg_count=base_entry_type.optional_arg_count)
if hasattr(base_entry.type, 'op_arg_struct'):
base_entry_type.op_arg_struct = base_entry.type.op_arg_struct
base_entry_type.original_alloc_type = base_entry.type.original_alloc_type
if base_entry.name in self.entries:
del self.entries[base_entry.name]
del self.entries["<constructor>"]
elif "<init>" in self.entries:
del self.entries["<constructor>"]
wrapper_entry = self.declare_constructor_wrapper(base_entry_type.args[1:],
base_entry.pos, defining=1,
has_varargs = base_entry_type.has_varargs,
optional_arg_count = base_entry_type.optional_arg_count,
op_arg_struct = getattr(base_entry_type, 'op_arg_struct', None),
return_type=base_entry_type.return_type)
wrapper_entry.is_inherited = 1
if base_entry.name in self.entries:
base_entry.name # FIXME: is there anything to do in this case?
entry = self.declare(base_entry.name, base_entry.cname,
......@@ -2560,7 +2660,9 @@ class CppClassScope(Scope):
name = "<init>"
elif name == "__dealloc__":
name = "<del>"
return super(CppClassScope, self).lookup_here(name)
elif name == "__alloc__":
name = "<alloc>"
return super(CppClassScope,self).lookup_here(name)
class PropertyScope(Scope):
......
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