is_cpp_class = 1
has_attributes = 1
exception_check = True
+ namespace = None
def __init__(self, name, scope, cname, base_classes, templates = None, template_type = None):
self.name = name
return self.specialize(dict(zip(self.templates, template_values)))
def specialize(self, values):
- if not self.templates:
+ if not self.templates and not self.namespace:
return self
+ if self.templates is None:
+ self.templates = []
key = tuple(values.items())
if key in self.specializations:
return self.specializations[key]
template_values = [t.specialize(values) for t in self.templates]
specialized = self.specializations[key] = \
CppClassType(self.name, None, self.cname, [], template_values, template_type=self)
- # Need to do these *after* self.specializations[key] is set to
- # avoid infinite recursion on circular references.
+ # Need to do these *after* self.specializations[key] is set
+ # to avoid infinite recursion on circular references.
specialized.base_classes = [b.specialize(values) for b in self.base_classes]
specialized.scope = self.scope.specialize(values)
+ if self.namespace is not None:
+ specialized.namespace = self.namespace.specialize(values)
return specialized
def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
if for_display or pyrex:
name = self.name
else:
- name = self.cname
+ if self.namespace is not None:
+ name = "%s::%s" % (self.namespace.declaration_code(''), self.cname)
+ else:
+ name = self.cname
return "%s%s %s" % (name, templates, entity_code)
def is_subclass(self, other_type):
is_py_class_scope = 0
is_c_class_scope = 0
+ is_cpp_class_scope = 0
is_module_scope = 0
scope_prefix = ""
in_cinclude = 0
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
return entry
+ def declare_cpp_class(self, name, scope,
+ pos, cname = None, base_classes = [],
+ visibility = 'extern', templates = None):
+ if visibility != 'extern':
+ error(pos, "C++ classes may only be extern")
+ if cname is None:
+ cname = name
+ entry = self.lookup(name)
+ if not entry:
+ type = PyrexTypes.CppClassType(
+ name, scope, cname, base_classes, templates = templates)
+ entry = self.declare_type(name, type, pos, cname,
+ visibility = visibility, defining = scope is not None)
+ else:
+ if not (entry.is_type and entry.type.is_cpp_class):
+ warning(pos, "'%s' redeclared " % name, 0)
+ elif scope and entry.type.scope:
+ warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
+ else:
+ if scope:
+ entry.type.scope = scope
+ self.type_entries.append(entry)
+ if not scope and not entry.type.scope:
+ entry.type.scope = CppClassScope(name, self)
+ if templates is not None:
+ for T in templates:
+ template_entry = entry.type.scope.declare(T.name, T.name, T, None, 'extern')
+ template_entry.is_type = 1
+
+ def declare_inherited_attributes(entry, base_classes):
+ for base_class in base_classes:
+ declare_inherited_attributes(entry, base_class.base_classes)
+ entry.type.scope.declare_inherited_cpp_attributes(base_class.scope)
+ declare_inherited_attributes(entry, base_classes)
+ if self.is_cpp_class_scope:
+ entry.type.namespace = self.outer_scope.lookup(self.name).type
+ return entry
+
def check_previous_typedef_flag(self, entry, typedef_flag, pos):
if typedef_flag != entry.type.typedef_flag:
error(pos, "'%s' previously declared using '%s'" % (
if typedef_flag and not self.in_cinclude:
error(pos, "Forward-referenced type must use 'cdef', not 'ctypedef'")
- def declare_cpp_class(self, name, scope,
- pos, cname = None, base_classes = [],
- visibility = 'extern', templates = None):
- if visibility != 'extern':
- error(pos, "C++ classes may only be extern")
- if cname is None:
- cname = name
- entry = self.lookup(name)
- if not entry:
- type = PyrexTypes.CppClassType(
- name, scope, cname, base_classes, templates = templates)
- entry = self.declare_type(name, type, pos, cname,
- visibility = visibility, defining = scope is not None)
- else:
- if not (entry.is_type and entry.type.is_cpp_class):
- warning(pos, "'%s' redeclared " % name, 0)
- elif scope and entry.type.scope:
- warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
- else:
- if scope:
- entry.type.scope = scope
- self.type_entries.append(entry)
- if not scope and not entry.type.scope:
- entry.type.scope = CppClassScope(name, self)
- if templates is not None:
- for T in templates:
- template_entry = entry.type.scope.declare(T.name, T.name, T, None, 'extern')
- template_entry.is_type = 1
-
- def declare_inherited_attributes(entry, base_classes):
- for base_class in base_classes:
- declare_inherited_attributes(entry, base_class.base_classes)
- entry.type.scope.declare_inherited_cpp_attributes(base_class.scope)
- declare_inherited_attributes(entry, base_classes)
- return entry
-
def allocate_vtable_names(self, entry):
# If extension type has a vtable, allocate vtable struct and
# slot names for it.
class CppClassScope(Scope):
# Namespace of a C++ class.
- inherited_var_entries = []
+
+ is_cpp_class_scope = 1
default_constructor = None
def __init__(self, name, outer_scope):
Scope.__init__(self, name, outer_scope, None)
self.directives = outer_scope.directives
+ self.inherited_var_entries = []
def declare_var(self, name, type, pos,
cname = None, visibility = 'extern', is_cdef = 0, allow_pyobject = 0):
def specialize(self, values):
scope = CppClassScope(self.name, self.outer_scope)
for entry in self.entries.values():
- scope.declare_var(entry.name,
- entry.type.specialize(values),
- entry.pos,
- entry.cname,
- entry.visibility)
+ if entry.is_type:
+ scope.declare_type(entry.name,
+ entry.type.specialize(values),
+ entry.pos,
+ entry.cname)
+ else:
+ scope.declare_var(entry.name,
+ entry.type.specialize(values),
+ entry.pos,
+ entry.cname,
+ entry.visibility)
return scope