greg: Tests passed
authorStefan Behnel <scoder@users.berlios.de>
Thu, 18 Oct 2007 07:43:42 +0000 (09:43 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Thu, 18 Oct 2007 07:43:42 +0000 (09:43 +0200)
Cython/Compiler/ExprNodes.py
Cython/Compiler/ModuleNode.py
Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py
Cython/Compiler/Symtab.py

index dad48de73e1f16439668a3fcb4c4c566ba978012..a4c760266609d49d98f82e3f241907db4452dcb2 100644 (file)
@@ -365,10 +365,7 @@ class ExprNode(Node):
             if debug_temp_alloc:
                 print self, "Allocated result", self.result_code
         else:
-            self.result_code = self.calculate_result_code_with_env(env)
-    
-    def calculate_result_code_with_env(self, env):
-        return self.calculate_result_code()
+            self.result_code = self.calculate_result_code()
     
     def target_code(self):
         #  Return code fragment for use as LHS of a C assignment.
@@ -790,6 +787,7 @@ class NameNode(AtomicExprNode):
             error(self.pos, "Assignment to non-lvalue '%s'"
                 % self.name)
             self.type = PyrexTypes.error_type
+        self.entry.used = 1
         
     def analyse_rvalue_entry(self, env):
         #print "NameNode.analyse_rvalue_entry:", self.name ###
@@ -858,20 +856,19 @@ class NameNode(AtomicExprNode):
         #  Name nodes are never ephemeral, even if the
         #  result is in a temporary.
         return 0
-
-    def calculate_result_code_with_env(self, env):
+    
+    def allocate_temp(self, env, result = None):
+        AtomicExprNode.allocate_temp(self, env, result)
         entry = self.entry
         if entry:
             entry.used = 1
             if entry.utility_code:
                 env.use_utility_code(entry.utility_code)
-        return self.calculate_result_code()
-    
+        
     def calculate_result_code(self):
         entry = self.entry
         if not entry:
             return "<error>" # There was an error earlier
-        entry.used = 1
         return entry.cname
     
     def generate_result_code(self, code):
index 90f96d0eebeb09abdf99ace7f4ad62acabc71e20..2de7964688084f2242426ca99f0f2eec933069a8 100644 (file)
@@ -57,23 +57,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         return 0
     
     def generate_h_code(self, env, options, result):
-        public_types = []
-        public_vars = []
-        public_funcs = []
-        public_extension_types = []
-        for entry in env.type_entries:
-            if entry.visibility == 'public':
-                public_types.append(entry)
-        for entry in env.var_entries:
-            if entry.visibility == 'public':
-                public_vars.append(entry)
-        for entry in env.cfunc_entries:
-            if entry.visibility == 'public' and not entry.in_cinclude:
-                public_funcs.append(entry)
-        for entry in env.c_class_entries:
-            if entry.visibility == 'public':
-                public_extension_types.append(entry)
-        if public_types or public_vars or public_funcs or public_extension_types:
+        def h_entries(entries, pxd = 0):
+            return [entry for entry in entries
+                if entry.visibility == 'public' or pxd and entry.defined_in_pxd]
+        h_types = h_entries(env.type_entries)
+        h_vars = h_entries(env.var_entries)
+        h_funcs = h_entries(env.cfunc_entries)
+        h_extension_types = h_entries(env.c_class_entries)
+        if h_types or h_vars or h_funcs or h_extension_types:
             result.h_file = replace_suffix(result.c_file, ".h")
             h_code = Code.CCodeWriter(open_new_file(result.h_file))
             if options.generate_pxi:
@@ -84,20 +75,20 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             guard = Naming.h_guard_prefix + env.qualified_name.replace(".", "__")
             h_code.put_h_guard(guard)
             self.generate_extern_c_macro_definition(h_code)
-            self.generate_type_header_code(public_types, h_code)
+            self.generate_type_header_code(h_types, h_code)
             h_code.putln("")
             h_code.putln("#ifndef %s" % Naming.api_guard_prefix + self.api_name(env))
-            if public_vars:
+            if h_vars:
                 h_code.putln("")
-                for entry in public_vars:
+                for entry in h_vars:
                     self.generate_public_declaration(entry, h_code, i_code)
-            if public_funcs:
+            if h_funcs:
                 h_code.putln("")
-                for entry in public_funcs:
+                for entry in h_funcs:
                     self.generate_public_declaration(entry, h_code, i_code)
-            if public_extension_types:
+            if h_extension_types:
                 h_code.putln("")
-                for entry in public_extension_types:
+                for entry in h_extension_types:
                     self.generate_cclass_header_code(entry.type, h_code)
                     if i_code:
                         self.generate_cclass_include_code(entry.type, i_code)
@@ -122,14 +113,17 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
     
     def generate_api_code(self, env, result):
         api_funcs = []
+        public_extension_types = []
+        has_api_extension_types = 0
         for entry in env.cfunc_entries:
             if entry.api:
                 api_funcs.append(entry)
-        public_extension_types = []
         for entry in env.c_class_entries:
             if entry.visibility == 'public':
                 public_extension_types.append(entry)
-        if api_funcs or public_extension_types:
+            if entry.api:
+                has_api_extension_types = 1
+        if api_funcs or has_api_extension_types:
             result.api_file = replace_suffix(result.c_file, "_api.h")
             h_code = Code.CCodeWriter(open_new_file(result.api_file))
             name = self.api_name(env)
@@ -156,16 +150,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             h_code.putln("#endif")
             if api_funcs:
                 h_code.putln("")
-                h_code.put_h_guard(Naming.api_func_guard + "import_function")
                 h_code.put(function_import_utility_code[1])
-                h_code.putln("")
-                h_code.putln("#endif")
             if public_extension_types:
                 h_code.putln("")
-                h_code.put_h_guard(Naming.api_func_guard + "import_type")
                 h_code.put(type_import_utility_code[1])
-                h_code.putln("")
-                h_code.putln("#endif")
             h_code.putln("")
             h_code.putln("static int import_%s(void) {" % name)
             h_code.putln("PyObject *module = 0;")
@@ -207,10 +195,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         else:
             i_code.putln("pass")
         i_code.dedent()
-
+    
     def generate_c_code(self, env, result):
-#              modules = []
-#              self.find_referenced_modules(env, modules, {})
         modules = self.referenced_modules
         code = Code.CCodeWriter(StringIO())
         code.h = Code.CCodeWriter(StringIO())
@@ -358,9 +344,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if definition:
             type_entries = env.type_entries
         else:
-            type_entries = [
-                entry for entry in env.type_entries
-                    if entry.defined_in_pxd]
+            type_entries = []
+            for entry in env.type_entries:
+                if entry.defined_in_pxd:
+                    type_entries.append(entry)
         self.generate_type_header_code(type_entries, code)
         for entry in env.c_class_entries:
             if not entry.in_cinclude:
@@ -1485,12 +1472,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             objstruct = type.objstruct_cname
         else:
             objstruct = "struct %s" % type.objstruct_cname
-#        code.putln('%s = __Pyx_ImportType("%s", "%s", sizeof(%s)); %s' % (
-#                      type.typeptr_cname,
-#                      type.module_name, 
-#                      type.name,
-#                      objstruct,
-#            code.error_goto_if_null(type.typeptr_cname, pos)))
         self.generate_type_import_call(type, code,
                                        code.error_goto_if_null(type.typeptr_cname, pos))
         self.use_type_import_utility_code(env)
@@ -1600,62 +1581,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.put(utility_code[1])
 
 #------------------------------------------------------------------------------------
-
-#type_import_utility_code = [
-#"""
-#static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, long size);  /*proto*/
-#""","""
-#static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, 
-#      long size) 
-#{
-#      PyObject *py_module_name = 0;
-#      PyObject *py_class_name = 0;
-#      PyObject *py_name_list = 0;
-#      PyObject *py_module = 0;
-#      PyObject *result = 0;
-#      
-#      py_module_name = PyString_FromString(module_name);
-#      if (!py_module_name)
-#              goto bad;
-#      py_class_name = PyString_FromString(class_name);
-#      if (!py_class_name)
-#              goto bad;
-#      py_name_list = PyList_New(1);
-#      if (!py_name_list)
-#              goto bad;
-#      Py_INCREF(py_class_name);
-#      if (PyList_SetItem(py_name_list, 0, py_class_name) < 0)
-#              goto bad;
-#      py_module = __Pyx_Import(py_module_name, py_name_list);
-#      if (!py_module)
-#              goto bad;
-#      result = PyObject_GetAttr(py_module, py_class_name);
-#      if (!result)
-#              goto bad;
-#      if (!PyType_Check(result)) {
-#              PyErr_Format(PyExc_TypeError, 
-#                      "%s.%s is not a type object",
-#                      module_name, class_name);
-#              goto bad;
-#      }
-#      if (((PyTypeObject *)result)->tp_basicsize != size) {
-#              PyErr_Format(PyExc_ValueError, 
-#                      "%s.%s does not appear to be the correct type object",
-#                      module_name, class_name);
-#              goto bad;
-#      }
-#      goto done;
-#bad:
-#      Py_XDECREF(result);
-#      result = 0;
-#done:
-#      Py_XDECREF(py_module_name);
-#      Py_XDECREF(py_class_name);
-#      Py_XDECREF(py_name_list);
-#      return (PyTypeObject *)result;
-#}
-#"""]
-
+#
+#  Runtime support code
+#
 #------------------------------------------------------------------------------------
 
 import_module_utility_code = [
@@ -1701,6 +1629,8 @@ type_import_utility_code = [
 """
 static PyTypeObject *__Pyx_ImportType(PyObject *py_module, char *module_name, char *class_name, long size);  /*proto*/
 ""","""
+#ifndef __PYX_HAVE_RT_ImportType
+#define __PYX_HAVE_RT_ImportType
 static PyTypeObject *__Pyx_ImportType(PyObject *py_module, char *module_name, char *class_name, long size) {
     PyObject *result = 0;
     
@@ -1724,6 +1654,7 @@ bad:
     Py_XDECREF(result);
     return 0;
 }
+#endif
 """]
 
 #------------------------------------------------------------------------------------
@@ -1765,6 +1696,8 @@ function_import_utility_code = [
 """
 static int __Pyx_ImportFunction(PyObject *module, char *funcname, void **f, char *sig); /*proto*/
 ""","""
+#ifndef __PYX_HAVE_RT_ImportFunction
+#define __PYX_HAVE_RT_ImportFunction
 static int __Pyx_ImportFunction(PyObject *module, char *funcname, void **f, char *sig) {
     PyObject *d = 0;
     PyObject *cobj = 0;
@@ -1798,4 +1731,5 @@ bad:
     Py_XDECREF(d);
     return -1;
 }
+#endif
 """ % dict(API = Naming.api_name)]
index 926c18e2cbc33bda46ee515cdddf38daa3a0c6a0..eba442bd4943210ecaaffc22b711ccd8cad4c8b7 100644 (file)
@@ -449,6 +449,7 @@ class CVarDefNode(StatNode):
     #  base_type     CBaseTypeNode
     #  declarators   [CDeclaratorNode]
     #  in_pxd        boolean
+    #  api           boolean
     
     def analyse_declarations(self, env, dest_scope = None):
         if not dest_scope:
@@ -470,13 +471,8 @@ class CVarDefNode(StatNode):
                 return
             if type.is_cfunction:
                 entry = dest_scope.declare_cfunction(name, type, declarator.pos,
-                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd)
-                #if self.visibility <> 'extern':
-                #      if self.in_pxd:
-                #              entry.defined_in_pxd = 1
-                #      else:
-                #              error(declarator.pos,
-                #                      "Non-extern C function declared but not defined")
+                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
+                    api = self.api)
             else:
                 if self.in_pxd and self.visibility != 'extern':
                     error(self.pos, 
@@ -499,6 +495,7 @@ class CStructOrUnionDefNode(StatNode):
     #  kind          "struct" or "union"
     #  typedef_flag  boolean
     #  visibility    "public" or "private"
+    #  in_pxd        boolean
     #  attributes    [CVarDefNode] or None
     #  entry         Entry
     
@@ -510,9 +507,11 @@ class CStructOrUnionDefNode(StatNode):
             self.name, self.kind, scope, self.typedef_flag, self.pos,
             self.cname, visibility = self.visibility)
         if self.attributes is not None:
+            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)
-
+    
     def analyse_expressions(self, env):
         pass
     
@@ -525,15 +524,19 @@ class CEnumDefNode(StatNode):
     #  cname          string or None
     #  items          [CEnumDefItemNode]
     #  typedef_flag   boolean
-    #  visibility    "public" or "private"
+    #  visibility     "public" or "private"
+    #  in_pxd         boolean
     #  entry          Entry
     
     def analyse_declarations(self, env):
         self.entry = env.declare_enum(self.name, self.pos,
             cname = self.cname, typedef_flag = self.typedef_flag,
             visibility = self.visibility)
-        for item in self.items:
-            item.analyse_declarations(env, self.entry)
+        if self.items is not None:
+            if self.in_pxd and not env.in_cinclude:
+                self.entry.defined_in_pxd = 1
+            for item in self.items:
+                item.analyse_declarations(env, self.entry)
 
     def analyse_expressions(self, env):
         pass
@@ -559,23 +562,23 @@ class CEnumDefItemNode(StatNode):
 
 
 class CTypeDefNode(StatNode):
-    #  base_type   CBaseTypeNode
-    #  declarator  CDeclaratorNode
-    #  visibility    "public" or "private"
+    #  base_type    CBaseTypeNode
+    #  declarator   CDeclaratorNode
+    #  visibility   "public" or "private"
+    #  in_pxd       boolean
     
     def analyse_declarations(self, env):
         base = self.base_type.analyse(env)
         name_declarator, type = self.declarator.analyse(base, env)
         name = name_declarator.name
         cname = name_declarator.cname
-        #if env.in_cinclude:
-        #      type = CTypedefType(cname, type)
-        env.declare_typedef(name, type, self.pos,
+        entry = env.declare_typedef(name, type, self.pos,
             cname = cname, visibility = self.visibility)
+        if self.in_pxd and not env.in_cinclude:
+            entry.defined_in_pxd = 1
     
     def analyse_expressions(self, env):
         pass
-    
     def generate_execution_code(self, code):
         pass
 
index bc1b3f37ff3bad26777690481d1a72411407b1a2..4550aa19eaf432d7e433ca886b8923ed58d96daa 100644 (file)
@@ -1728,9 +1728,9 @@ def p_cdef_statement(s, level, visibility = 'private', api = 0,
         #if api:
         #    error(pos, "'api' not allowed with '%s'" % s.systring)
         if s.systring == "enum":
-            return p_c_enum_definition(s, pos, visibility)
+            return p_c_enum_definition(s, pos, level, visibility)
         else:
-            return p_c_struct_or_union_definition(s, pos, visibility)
+            return p_c_struct_or_union_definition(s, pos, level, visibility)
     elif s.sy == 'pass':
         node = p_pass_statement(s)
         s.expect_newline('Expected a newline')
@@ -1758,7 +1758,7 @@ struct_union_or_enum = (
     "struct", "union", "enum"
 )
 
-def p_c_enum_definition(s, pos, visibility, typedef_flag = 0):
+def p_c_enum_definition(s, pos, level, visibility, typedef_flag = 0):
     # s.sy == ident 'enum'
     s.next()
     if s.sy == 'IDENT':
@@ -1781,7 +1781,8 @@ def p_c_enum_definition(s, pos, visibility, typedef_flag = 0):
             p_c_enum_line(s, items)
         s.expect_dedent()
     return Nodes.CEnumDefNode(pos, name = name, cname = cname,
-        items = items, typedef_flag = typedef_flag, visibility = visibility)
+        items = items, typedef_flag = typedef_flag, visibility = visibility,
+        in_pxd = level == 'module_pxd')
 
 def p_c_enum_line(s, items):
     if s.sy <> 'pass':
@@ -1806,7 +1807,7 @@ def p_c_enum_item(s, items):
     items.append(Nodes.CEnumDefItemNode(pos, 
         name = name, cname = cname, value = value))
 
-def p_c_struct_or_union_definition(s, pos, visibility, typedef_flag = 0):
+def p_c_struct_or_union_definition(s, pos, level, visibility, typedef_flag = 0):
     # s.sy == ident 'struct' or 'union'
     kind = s.systring
     s.next()
@@ -1831,7 +1832,8 @@ def p_c_struct_or_union_definition(s, pos, visibility, typedef_flag = 0):
         s.expect_newline("Syntax error in struct or union definition")
     return Nodes.CStructOrUnionDefNode(pos, 
         name = name, cname = cname, kind = kind, attributes = attributes,
-        typedef_flag = typedef_flag, visibility = visibility)
+        typedef_flag = typedef_flag, visibility = visibility,
+        in_pxd = level == 'module_pxd')
 
 def p_visibility(s, prev_visibility):
     pos = s.position()
@@ -1884,7 +1886,8 @@ def p_c_func_or_var_declaration(s, level, pos, visibility = 'private', api = 0,
             visibility = visibility,
             base_type = base_type, 
             declarators = declarators,
-            in_pxd = level == 'module_pxd')
+            in_pxd = level == 'module_pxd',
+            api = api)
     return result
 
 def p_ctypedef_statement(s, level, visibility = 'private', api = 0):
@@ -1897,15 +1900,17 @@ def p_ctypedef_statement(s, level, visibility = 'private', api = 0):
             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)
+            return p_c_enum_definition(s, pos, level, visibility, typedef_flag = 1)
         else:
-            return p_c_struct_or_union_definition(s, pos, visibility, typedef_flag = 1)
+            return p_c_struct_or_union_definition(s, pos, level, visibility,
+                typedef_flag = 1)
     else:
         base_type = p_c_base_type(s)
         declarator = p_c_declarator(s, is_type = 1, nonempty = 1)
         s.expect_newline("Syntax error in ctypedef statement")
         return Nodes.CTypeDefNode(pos,
-            base_type = base_type, declarator = declarator, visibility = visibility)
+            base_type = base_type, declarator = declarator, visibility = visibility,
+            in_pxd = level == 'module_pxd')
 
 def p_def_statement(s):
     # s.sy == 'def'
index 350004f0c7f1dc65bbe56bf4fd484af201803748..a1c14ff8126662d3f3ba6870b7652b6dc202d73b 100644 (file)
@@ -267,6 +267,7 @@ class Scope:
         type = PyrexTypes.CTypedefType(cname, base_type)
         entry = self.declare_type(name, type, pos, cname, visibility)
         type.qualified_name = entry.qualified_name
+        return entry
         
     def declare_struct_or_union(self, name, kind, scope, 
             typedef_flag, pos, cname = None, visibility = 'private'):