Commit 0f319c23 authored by Stefan Behnel's avatar Stefan Behnel

General cdef block

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