Cpp class scope and type
authorDaniloFreitas <dsurviver@gmail.com>
Tue, 9 Jun 2009 02:57:03 +0000 (19:57 -0700)
committerDaniloFreitas <dsurviver@gmail.com>
Tue, 9 Jun 2009 02:57:03 +0000 (19:57 -0700)
Cython/Compiler/ModuleNode.py
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py
Cython/Compiler/PyrexTypes.py
Cython/Compiler/Symtab.py

index 32be4c715e26ea1f2c0345ffdc7960d0f949cf10..2d10b4c4f81246057f14f5483bac47f902e1e2f2 100644 (file)
@@ -703,6 +703,35 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 code.putln("#pragma pack(pop)")
                 code.putln("#endif")
 
+    def generate_cpp_class_definition(self, entry, code):
+        code.mark_pos(entry.pos)\r
+        type = entry.type\r
+        scope = type.scope\r
+        if scope:\r
+            kind = type.kind\r
+            packed = type.is_cpp_class and type.packed\r
+            if packed:\r
+                kind = "%s %s" % (type.kind, "__Pyx_PACKED")\r
+                code.globalstate.use_utility_code(packed_struct_utility_code)\r
+            header, footer = \\r
+                self.sue_header_footer(type, kind, type.cname)\r
+            code.putln("")\r
+            if packed:\r
+                code.putln("#if !defined(__GNUC__)")\r
+                code.putln("#pragma pack(push, 1)")\r
+                code.putln("#endif")\r
+            code.putln(header)\r
+            var_entries = scope.var_entries\r
+            for attr in var_entries:\r
+                code.putln(\r
+                    "%s;" %\r
+                        attr.type.declaration_code(attr.cname))\r
+            code.putln(footer)\r
+            if packed:\r
+                code.putln("#if !defined(__GNUC__)")\r
+                code.putln("#pragma pack(pop)")\r
+                code.putln("#endif")\r
+\r
     def generate_enum_definition(self, entry, code):
         code.mark_pos(entry.pos)
         type = entry.type
index ef78b1fca2c4430f8a327a27fbaa8e5fdd4b4de7..f2ebeb038a742ac40a7a428af8636092508d3242 100644 (file)
@@ -914,18 +914,20 @@ class CppClassNode(CStructOrUnionDefNode):
 
     #  name          string
     #  cname         string or None
-    #  visibility    "public" or "private"
+    #  visibility    "extern"\r
     #  in_pxd        boolean
     #  attributes    [CVarDefNode] or None
     #  entry         Entry
+    #  base_classes  [string]
+    #  namespace     string or None\r
 
     def analyse_declarations(self, env):
         scope = None
         if self.attributes is not None:
-            scope = StructOrUnionScope(self.name) # for now
-        self.entry = env.declare_struct_or_union(
-            self.name, "struct", scope, 0, self.pos,
-            self.cname, visibility = self.visibility)
+            scope = CppClassScope(self.name)\r
+        self.entry = env.declare_cpp_class(\r
+            self.name, "cppclass", scope, 0, self.pos,\r
+            self.cname, self.base_classes, self.namespace, visibility = self.visibility)\r
         if self.attributes is not None:
             if self.in_pxd and not env.in_cinclude:
                 self.entry.defined_in_pxd = 1
index 82cb512b964688b4b0ab875531fe4842e86c389e..10f6bdad8c606fc1ec5375ebc0a87e313407201d 100644 (file)
@@ -31,6 +31,7 @@ class Ctx(object):
     api = 0
     overridable = 0
     nogil = 0
+    namespace = None\r
 
     def __init__(self, **kwds):
         self.__dict__.update(kwds)
@@ -2123,7 +2124,7 @@ def p_cdef_extern_block(s, pos, ctx):
         _, include_file = p_string_literal(s)
     if s.systring == "namespace":
         s.next()
-        namespace = p_ident(s)
+        ctx.namespace = p_ident(s)\r
     ctx = ctx(cdef_flag = 1, visibility = 'extern')
     if p_nogil(s):
         ctx.nogil = 1
@@ -2533,9 +2534,6 @@ def p_module(s, pxd, full_module_name):
                       full_module_name = full_module_name,
                       option_comments = option_comments)
 
-
-#Implementing...
-
 def p_cpp_class_definition(s, pos,  ctx):
     # s.sy == 'cppclass'
     s.next()
@@ -2584,15 +2582,12 @@ def p_cpp_class_definition(s, pos,  ctx):
         s.expect_newline("Syntax error in C++ class definition")
     return Nodes.CppClassNode(pos,
         name = class_name,
-        namespace = None,
         cname = None,
         base_classes = base_classes,
+        namespace = ctx.namespace,\r
         visibility = ctx.visibility,
         in_pxd = ctx.level == 'module_pxd',
-        attributes = None)
-
-def p_cpp_class(s):
-    pass
+        attributes = attributes)\r
 
 
 
index f01b5174de0e6a49d2d29510942dcb5adf91f54e..b8da65700c2b93234665308e27088c3ff53f0029 100644 (file)
@@ -91,6 +91,7 @@ class PyrexType(BaseType):
     is_null_ptr = 0
     is_cfunction = 0
     is_struct_or_union = 0
+    is_cpp_class = 0\r
     is_struct = 0
     is_enum = 0
     is_typedef = 0
@@ -1342,6 +1343,57 @@ class CStructOrUnionType(CType):
                         for x in self.scope.var_entries]
         return max(child_depths) + 1
 
+class CppClassType(CType):\r
+    #  name          string\r
+    #  cname         string\r
+    #  kind          string              "cppclass"\r
+    #  scope         CppClassScope\r
+    #  typedef_flag  boolean\r
+    #  packed        boolean\r
+    \r
+    is_cpp_class = 1\r
+    has_attributes = 1\r
+    base_classes = []
+    namespace = None\r
+    \r
+    def __init__(self, name, kind, scope, typedef_flag, cname, base_classes,
+                 namespace = None, packed=False):\r
+        self.name = name\r
+        self.cname = cname\r
+        self.kind = kind\r
+        self.scope = scope\r
+        self.typedef_flag = typedef_flag\r
+        self.exception_check = True\r
+        self._convert_code = None\r
+        self.packed = packed\r
+        self.base_classes = base_classes
+        self.namespace = namespace\r
+\r
+    def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
+        inherited = ""
+        for base_class in self.base_classes:
+            if inherited != "":
+                inherited += " : public "
+            inherited += base_class
+            if base_class != baseclasses[-1]:
+                inherited += " , "
+        return "%s%s" % (self.name, inherited)
+            \r
+\r
+    def is_subclass(self, other_type):\r
+        if not base_classes.empty():\r
+            for base_class in self.base_classes:\r
+                if base_class.is_subclass(other_type):\r
+                    return 1\r
+        return 0\r
+\r
+    def assignable_from_resolved_type(self, other_type):\r
+        if self.same_as_resolved_type(other_type):\r
+            return 1\r
+        if self.is_subclass(other) or self.same_as(other_type):\r
+            return 1\r
+        return 0\r
+\r
 class CEnumType(CType):
     #  name           string
     #  cname          string or None
index 76448f5561559b2ba38250edf02974f3bfaf9a14..a3430d6e6b371382c7f81e05675822c67a96ced4 100644 (file)
@@ -384,6 +384,32 @@ class Scope(object):
             self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
         return entry
     
+    def declare_cpp_class(self, name, kind, scope,\r
+            typedef_flag, pos, cname = None, base_classes = [], namespace = None,
+            visibility = 'extern', packed = False):\r
+        if visibility != 'extern':\r
+            error(pos, "C++ classes may only be extern")\r
+        if not entry:\r
+            type = PyrexTypes.CppClassType(\r
+                name, kind, scope, typedef_flag, cname, base_classes, namespace, packed)\r
+            entry = self.declare_type(name, type, pos, cname,\r
+                visibility = visibility, defining = scope is not None)\r
+            self.sue_entries.append(entry)\r
+        else:\r
+            if not (entry.is_type and entry.type.is_cpp_class\r
+                    and entry.type.kind == kind):\r
+                warning(pos, "'%s' redeclared  " % name, 0)\r
+            elif scope and entry.type.scope:\r
+                warning(pos, "'%s' already defined  (ignoring second definition)" % name, 0)\r
+            else:\r
+                self.check_previous_typedef_flag(entry, typedef_flag, pos)\r
+                if scope:\r
+                    entry.type.scope = scope\r
+                    self.type_entries.append(entry)\r
+        if not scope and not entry.type.scope:\r
+            self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)\r
+        return entry\r
+    \r
     def check_previous_typedef_flag(self, entry, typedef_flag, pos):
         if typedef_flag != entry.type.typedef_flag:
             error(pos, "'%s' previously declared using '%s'" % (