Declaring and using inherited attributes
authorDanilo Freitas <dsurviver@gmail.com>
Wed, 17 Jun 2009 13:40:11 +0000 (10:40 -0300)
committerDanilo Freitas <dsurviver@gmail.com>
Wed, 17 Jun 2009 13:40:11 +0000 (10:40 -0300)
Cython/Compiler/ModuleNode.py
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.pxd
Cython/Compiler/Parsing.py
Cython/Compiler/PyrexTypes.py
Cython/Compiler/Symtab.py

index 161df8e5656b02e22559f7915810d84e7323176f..2f28f4e2446b41884b208e29237929ba017ad595 100644 (file)
@@ -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:
index ad43e45917f6e053b5ccd3eb34c083d2365a7512..63d3bc72f4884a161b71db7e0cfedc23ab43771d 100644 (file)
@@ -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
index 57532e4359117c3789532027af24079af01be998..8cda7b896c6be711c7d60b6848a755d2f56abec0 100644 (file)
@@ -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)
+
index f0a9d4214cb20e14215d1965893d6907533a926e..333a06b6953792b9a1074279011d193fa0fdf7af 100644 (file)
@@ -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()
index 001beb25de06adacd031b53dedc43f4b57e16c1d..9bd28744a86c0c7afd076651018f8494c26ea48e 100644 (file)
@@ -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
 
index 32ce96ed399846a7db8765382071e2bdb28873d5..d44c30ed6ce587ba71c78adfbb1e1a28be8e9b88 100644 (file)
@@ -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)