From: Danilo Freitas Date: Wed, 17 Jun 2009 13:40:11 +0000 (-0300) Subject: Declaring and using inherited attributes X-Git-Tag: 0.13.beta0~353^2~81 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=533ae132168d5f2c07e6c5382dad1ca5a66ae5c9;p=cython.git Declaring and using inherited attributes --- diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 161df8e5..2f28f4e2 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -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: diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index ad43e459..63d3bc72 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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 diff --git a/Cython/Compiler/Parsing.pxd b/Cython/Compiler/Parsing.pxd index 57532e43..8cda7b89 100644 --- a/Cython/Compiler/Parsing.pxd +++ b/Cython/Compiler/Parsing.pxd @@ -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) + diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index f0a9d421..333a06b6 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -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() diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index 001beb25..9bd28744 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -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 diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 32ce96ed..d44c30ed 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -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)