Commit 533ae132 authored by Danilo Freitas's avatar Danilo Freitas

Declaring and using inherited attributes

parent 907de12e
......@@ -390,6 +390,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_typedef(entry, code)
elif type.is_struct_or_union:
self.generate_struct_union_definition(entry, code)
elif type.is_cpp_class:
self.generate_cpp_class_definition(entry, code)
elif type.is_enum:
self.generate_enum_definition(entry, code)
elif type.is_extension_type and entry not in vtabslot_entries:
......@@ -637,6 +639,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_typedef(entry, code)
elif type.is_struct_or_union:
self.generate_struct_union_definition(entry, code)
elif type.is_cpp_class:
self.generate_cpp_class_definition(entry, code)
elif type.is_enum:
self.generate_enum_definition(entry, code)
elif type.is_extension_type:
......
......@@ -916,8 +916,10 @@ class CppClassNode(CStructOrUnionDefNode):
def analyse_declarations(self, env):
scope = None
if self.attributes is not None:
if len(self.attributes) != 0:
scope = CppClassScope(self.name)
else:
self.attributes = None
self.entry = env.declare_cpp_class(
self.name, "cppclass", scope, 0, self.pos,
self.cname, self.base_classes, self.namespace, visibility = self.visibility)
......@@ -925,7 +927,7 @@ class CppClassNode(CStructOrUnionDefNode):
if self.in_pxd and not env.in_cinclude:
self.entry.defined_in_pxd = 1
for attr in self.attributes:
attr.analyse_declarations(env, scope)
attr.analyse_declarations(env, scope)
class CEnumDefNode(StatNode):
# name string or None
......
......@@ -149,3 +149,5 @@ cpdef p_doc_string(PyrexScanner s)
cpdef p_code(PyrexScanner s, level= *)
cpdef p_compiler_directive_comments(PyrexScanner s)
cpdef p_module(PyrexScanner s, pxd, full_module_name)
cpdef p_cpp_class_definition(PyrexScanner s, ctx)
......@@ -2564,7 +2564,6 @@ def p_cpp_class_definition(s, pos, ctx):
if s.sy == '[':
error(s.position(), "Name options not allowed for C++ class")
if s.sy == ':':
attributes = None
s.next()
s.expect('NEWLINE')
s.expect_indent()
......
......@@ -1372,7 +1372,7 @@ class CppClassType(CType):
has_attributes = 1
base_classes = []
namespace = None
def __init__(self, name, kind, scope, typedef_flag, cname, base_classes,
namespace = None, packed=False):
self.name = name
......@@ -1396,16 +1396,18 @@ class CppClassType(CType):
return "%s %s" % (name, entity_code)
def is_subclass(self, other_type):
if not base_classes.empty():
for base_class in self.base_classes:
if base_class.is_subclass(other_type):
return 1
for base_class in self.base_classes:
if base_class.is_subclass(other_type):
return 1
return 0
def assignable_from_resolved_type(self, other_type):
print self.same_as_resolved_type(other_type)
print self.same_as(other_type)
print other_type.is_subclass(self)
if self.same_as_resolved_type(other_type):
return 1
if other.is_subclass(self) or self.same_as(other_type):
if other_type.is_subclass(self) or self.same_as(other_type):
return 1
return 0
......
......@@ -384,34 +384,6 @@ class Scope(object):
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
return entry
def declare_cpp_class(self, name, kind, scope,
typedef_flag, pos, cname = None, base_classes = [], namespace = None,
visibility = 'extern', packed = False):
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, kind, scope, typedef_flag, cname, base_classes, namespace, packed)
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
and entry.type.kind == kind):
warning(pos, "'%s' redeclared " % name, 0)
elif scope and entry.type.scope:
warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
else:
self.check_previous_typedef_flag(entry, typedef_flag, pos)
if scope:
entry.type.scope = scope
self.type_entries.append(entry)
if not scope and not entry.type.scope:
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
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'" % (
......@@ -1122,6 +1094,44 @@ class ModuleScope(Scope):
#
return entry
def declare_cpp_class(self, name, kind, scope,
typedef_flag, pos, cname = None, base_classes = [], namespace = None,
visibility = 'extern', packed = False):
def declare_inherited_attributes(entry, base_entry):
if base_entry:
for base_class in base_entry.type.base_classes:
new_entry = self.lookup(base_class)
if base_entry:
declare_inherited_attributes(entry, new_entry)
entry.type.scope.declare_inherited_cpp_attributes(new_entry.type.scope)
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, kind, scope, typedef_flag, cname, base_classes, namespace, packed)
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
and entry.type.kind == kind):
warning(pos, "'%s' redeclared " % name, 0)
elif scope and entry.type.scope:
warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
else:
self.check_previous_typedef_flag(entry, typedef_flag, pos)
if scope:
entry.type.scope = scope
self.type_entries.append(entry)
if not scope and not entry.type.scope:
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
entry.type.scope = CppClassScope(name)
declare_inherited_attributes(entry, entry)
return entry
def check_for_illegal_incomplete_ctypedef(self, typedef_flag, pos):
if typedef_flag and not self.in_cinclude:
error(pos, "Forward-referenced type must use 'cdef', not 'ctypedef'")
......@@ -1582,6 +1592,7 @@ class CClassScope(ClassScope):
class CppClassScope(Scope):
# Namespace of a C++ class.
inherited_var_entries = []
def __init__(self, name="?"):
Scope.__init__(self, name, None, None)
......@@ -1591,8 +1602,6 @@ class CppClassScope(Scope):
# Add an entry for an attribute.
if not cname:
cname = name
if visibility != 'extern':
error(pos, "Visibility for C++ class member are extern only")
if type.is_cfunction:
type = PyrexTypes.CPtrType(type)
entry = self.declare(name, cname, type, pos, visibility)
......
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