General cdef block
authorStefan Behnel <scoder@users.berlios.de>
Thu, 18 Oct 2007 06:44:40 +0000 (08:44 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Thu, 18 Oct 2007 06:44:40 +0000 (08:44 +0200)
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py
Cython/Compiler/Symtab.py

index d5bb76ecc69bc7364bf2af982a4f4f809a5652ac..926c18e2cbc33bda46ee515cdddf38daa3a0c6a0 100644 (file)
@@ -807,6 +807,7 @@ class CFuncDefNode(FuncDefNode):
     def generate_function_header(self, code, with_pymethdef):
         arg_decls = []
         type = self.type
+        visibility = self.entry.visibility
         for arg in type.args:
             arg_decls.append(arg.declaration_code())
         if type.has_varargs:
@@ -815,18 +816,16 @@ class CFuncDefNode(FuncDefNode):
             arg_decls = ["void"]
         entity = type.function_header_code(self.entry.func_cname,
             string.join(arg_decls, ","))
-        if self.visibility == 'public':
+        if visibility == 'public':
             dll_linkage = "DL_EXPORT"
         else:
             dll_linkage = None
         header = self.return_type.declaration_code(entity,
             dll_linkage = dll_linkage)
-        if self.visibility == 'private':
-            storage_class = "static "
-        elif self.visibility == 'extern':
+        if visibility <> 'private':
             storage_class = "%s " % Naming.extern_c_macro
         else:
-            storage_class = ""
+            storage_class = "static "
         code.putln("%s%s %s {" % (
             storage_class,
             ' '.join(self.modifiers).upper(), # macro forms 
@@ -1476,6 +1475,7 @@ class CClassDefNode(StatNode):
     #
     #  visibility         'private' or 'public' or 'extern'
     #  typedef_flag       boolean
+    #  api                boolean
     #  module_name        string or None    For import of extern type objects
     #  class_name         string            Unqualified name of class
     #  as_name            string or None    Name to declare as in this scope
@@ -1524,7 +1524,8 @@ class CClassDefNode(StatNode):
             objstruct_cname = self.objstruct_name,
             typeobj_cname = self.typeobj_name,
             visibility = self.visibility,
-            typedef_flag = self.typedef_flag)
+            typedef_flag = self.typedef_flag,
+            api = self.api)
         scope = self.entry.type.scope
 
         if self.doc:
index 3bcc01b13cb2768838fdf6e53364aa18ee9c8843..bc1b3f37ff3bad26777690481d1a72411407b1a2 100644 (file)
@@ -1301,7 +1301,7 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0):
             s.error("ctypedef statement not allowed here")
         if api:
             error(s.pos, "'api' not allowed with 'ctypedef'")
-        return p_ctypedef_statement(s, level, visibility)
+        return p_ctypedef_statement(s, level, visibility, api)
     elif s.sy == 'DEF':
         return p_DEF_statement(s)
     elif s.sy == 'IF':
@@ -1713,20 +1713,20 @@ def p_cdef_statement(s, level, visibility = 'private', api = 0,
     if visibility == 'extern' and s.sy == 'from':
             return p_cdef_extern_block(s, level, pos)
     elif s.sy == ':':
-        p_cdef_block(s, level, visibility, api)
+        return p_cdef_block(s, level, visibility, api)
     elif s.sy == 'class':
         if level not in ('module', 'module_pxd'):
             error(pos, "Extension type definition not allowed here")
-        if api:
-            error(pos, "'api' not allowed with extension class")
-        return p_c_class_definition(s, level, pos, visibility = visibility)
+        #if api:
+        #    error(pos, "'api' not allowed with extension class")
+        return p_c_class_definition(s, level, pos, visibility = visibility, api = api)
     elif s.sy == 'IDENT' and s.systring in struct_union_or_enum:
         if level not in ('module', 'module_pxd'):
             error(pos, "C struct/union/enum definition not allowed here")
         #if visibility == 'public':
         #    error(pos, "Public struct/union/enum definition not implemented")
-        if api:
-            error(pos, "'api' not allowed with '%s'" % s.systring)
+        #if api:
+        #    error(pos, "'api' not allowed with '%s'" % s.systring)
         if s.systring == "enum":
             return p_c_enum_definition(s, pos, visibility)
         else:
@@ -1740,8 +1740,7 @@ def p_cdef_statement(s, level, visibility = 'private', api = 0,
                                            overridable)
 
 def p_cdef_block(s, level, visibility, api):
-    body = p_suite(s, level, cdef_flag = 1, visibility = 'extern', api = api)
-    return Nodes.StatListNode(pos, stats = body)
+    return p_suite(s, level, cdef_flag = 1, visibility = visibility, api = api)
 
 def p_cdef_extern_block(s, level, pos):
     include_file = None
@@ -1871,8 +1870,8 @@ def p_c_func_or_var_declaration(s, level, pos, visibility = 'private', api = 0,
             api = api,
             overridable = overridable)
     else:
-        if api:
-            error(s.pos, "'api' not allowed with variable declaration")
+        #if api:
+        #    error(s.pos, "'api' not allowed with variable declaration")
         declarators = [declarator]
         while s.sy == ',':
             s.next()
@@ -1888,15 +1887,14 @@ def p_c_func_or_var_declaration(s, level, pos, visibility = 'private', api = 0,
             in_pxd = level == 'module_pxd')
     return result
 
-def p_ctypedef_statement(s, level, visibility = 'private'):
+def p_ctypedef_statement(s, level, visibility = 'private', api = 0):
     # s.sy == 'ctypedef'
     pos = s.position()
     s.next()
     visibility = p_visibility(s, visibility)
     if s.sy == 'class':
         return p_c_class_definition(s, level, pos,
-            visibility = visibility,
-            typedef_flag = 1)
+            visibility = visibility, typedef_flag = 1, api = api)
     elif s.sy == 'IDENT' and s.systring in ('struct', 'union', 'enum'):
         if s.systring == 'enum':
             return p_c_enum_definition(s, pos, visibility, typedef_flag = 1)
@@ -1963,7 +1961,7 @@ def p_class_statement(s):
         doc = doc, body = body)
 
 def p_c_class_definition(s, level, pos, 
-        visibility = 'private', typedef_flag = 0):
+        visibility = 'private', typedef_flag = 0, api = 0):
     # s.sy == 'class'
     s.next()
     module_path = []
@@ -2019,9 +2017,13 @@ def p_c_class_definition(s, level, pos,
             error(pos, "Object struct name specification required for 'public' C class")
         if not typeobj_name:
             error(pos, "Type object name specification required for 'public' C class")
+    else:
+        if api:
+            error(pos, "Only 'public' C class can be declared 'api'")
     return Nodes.CClassDefNode(pos,
         visibility = visibility,
         typedef_flag = typedef_flag,
+        api = api,
         module_name = ".".join(module_path),
         class_name = class_name,
         as_name = as_name,
index 9a84ca8bd233a6eb13709e04ea91a98a37995cfc..eea970f6bb438907f929822b58d96dbd75441917 100644 (file)
@@ -68,7 +68,7 @@ class Entry:
     # is_special       boolean    Is a special method or property accessor
     #                               of an extension type
     # defined_in_pxd   boolean    Is defined in a .pxd file (not just declared)
-    # api              boolean    Generate C API for C function
+    # api              boolean    Generate C API for C class or function
 
     borrowed = 0
     init = ""
@@ -353,6 +353,9 @@ class Scope:
         # Add an entry for a C function.
         entry = self.lookup_here(name)
         if entry:
+            if visibility <> 'private' and visibility <> entry.visibility:
+                error(pos, "Function '%s' previously declared as '%s'" % (
+                    name, entry.visibility))
             if not entry.type.same_as(type):
                 error(pos, "Function signature does not match previous declaration")
         else:
@@ -823,7 +826,7 @@ class ModuleScope(Scope):
     
     def declare_c_class(self, name, pos, defining, implementing,
         module_name, base_type, objstruct_cname, typeobj_cname,
-        visibility, typedef_flag):
+        visibility, typedef_flag, api):
         #
         # Look for previous declaration as a type
         #
@@ -882,9 +885,11 @@ class ModuleScope(Scope):
             entry.defined_in_pxd = 1
         if implementing:   # So that filenames in runtime exceptions refer to
             entry.pos = pos  # the .pyx file and not the .pxd file
-        if entry.visibility <> visibility:
-            error(pos, "Declaration of '%s' as '%s' conflicts with previous "
-                "declaration as '%s'" % (name, visibility, entry.visibility))
+        if visibility <> 'private' and entry.visibility <> visibility:
+            error(pos, "Class '%s' previously declared as '%s'"
+                % (name, entry.visibility))
+        if api:
+            entry.api = 1
         if objstruct_cname:
             if type.objstruct_cname and type.objstruct_cname <> objstruct_cname:
                 error(pos, "Object struct name differs from previous declaration")