From b9d0602083c91f7c8f7fe965bd023bf4d5c3b709 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 18 Oct 2007 09:43:42 +0200 Subject: [PATCH] greg: Tests passed --- Cython/Compiler/ExprNodes.py | 15 ++-- Cython/Compiler/ModuleNode.py | 134 +++++++++------------------------- Cython/Compiler/Nodes.py | 39 +++++----- Cython/Compiler/Parsing.py | 25 ++++--- Cython/Compiler/Symtab.py | 1 + 5 files changed, 77 insertions(+), 137 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index dad48de7..a4c76026 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -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 "" # There was an error earlier - entry.used = 1 return entry.cname def generate_result_code(self, code): diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 90f96d0e..2de79646 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -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)] diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 926c18e2..eba442bd 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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 diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index bc1b3f37..4550aa19 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -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' diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 350004f0..a1c14ff8 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -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'): -- 2.26.2