From 0f319c23feb386cfbf080c8ae413b998251a1378 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 18 Oct 2007 08:44:40 +0200 Subject: [PATCH] General cdef block --- Cython/Compiler/Nodes.py | 13 +++++++------ Cython/Compiler/Parsing.py | 32 +++++++++++++++++--------------- Cython/Compiler/Symtab.py | 15 ++++++++++----- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index d5bb76ec..926c18e2 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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: diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index 3bcc01b1..bc1b3f37 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -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, diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 9a84ca8b..eea970f6 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -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") -- 2.26.2