From: DaniloFreitas Date: Tue, 9 Jun 2009 02:57:03 +0000 (-0700) Subject: Cpp class scope and type X-Git-Tag: 0.13.beta0~353^2~86 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=136f8912af439a07db420489cc8d693ed3333652;p=cython.git Cpp class scope and type --- diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index 32be4c71..2d10b4c4 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -703,6 +703,35 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln("#pragma pack(pop)") code.putln("#endif") + def generate_cpp_class_definition(self, entry, code): + code.mark_pos(entry.pos) + type = entry.type + scope = type.scope + if scope: + kind = type.kind + packed = type.is_cpp_class and type.packed + if packed: + kind = "%s %s" % (type.kind, "__Pyx_PACKED") + code.globalstate.use_utility_code(packed_struct_utility_code) + header, footer = \ + self.sue_header_footer(type, kind, type.cname) + code.putln("") + if packed: + code.putln("#if !defined(__GNUC__)") + code.putln("#pragma pack(push, 1)") + code.putln("#endif") + code.putln(header) + var_entries = scope.var_entries + for attr in var_entries: + code.putln( + "%s;" % + attr.type.declaration_code(attr.cname)) + code.putln(footer) + if packed: + code.putln("#if !defined(__GNUC__)") + code.putln("#pragma pack(pop)") + code.putln("#endif") + def generate_enum_definition(self, entry, code): code.mark_pos(entry.pos) type = entry.type diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index ef78b1fc..f2ebeb03 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -914,18 +914,20 @@ class CppClassNode(CStructOrUnionDefNode): # name string # cname string or None - # visibility "public" or "private" + # visibility "extern" # in_pxd boolean # attributes [CVarDefNode] or None # entry Entry + # base_classes [string] + # namespace string or None def analyse_declarations(self, env): scope = None if self.attributes is not None: - scope = StructOrUnionScope(self.name) # for now - self.entry = env.declare_struct_or_union( - self.name, "struct", scope, 0, self.pos, - self.cname, visibility = self.visibility) + scope = CppClassScope(self.name) + self.entry = env.declare_cpp_class( + self.name, "cppclass", scope, 0, self.pos, + self.cname, self.base_classes, self.namespace, visibility = self.visibility) if self.attributes is not None: if self.in_pxd and not env.in_cinclude: self.entry.defined_in_pxd = 1 diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index 82cb512b..10f6bdad 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -31,6 +31,7 @@ class Ctx(object): api = 0 overridable = 0 nogil = 0 + namespace = None def __init__(self, **kwds): self.__dict__.update(kwds) @@ -2123,7 +2124,7 @@ def p_cdef_extern_block(s, pos, ctx): _, include_file = p_string_literal(s) if s.systring == "namespace": s.next() - namespace = p_ident(s) + ctx.namespace = p_ident(s) ctx = ctx(cdef_flag = 1, visibility = 'extern') if p_nogil(s): ctx.nogil = 1 @@ -2533,9 +2534,6 @@ def p_module(s, pxd, full_module_name): full_module_name = full_module_name, option_comments = option_comments) - -#Implementing... - def p_cpp_class_definition(s, pos, ctx): # s.sy == 'cppclass' s.next() @@ -2584,15 +2582,12 @@ def p_cpp_class_definition(s, pos, ctx): s.expect_newline("Syntax error in C++ class definition") return Nodes.CppClassNode(pos, name = class_name, - namespace = None, cname = None, base_classes = base_classes, + namespace = ctx.namespace, visibility = ctx.visibility, in_pxd = ctx.level == 'module_pxd', - attributes = None) - -def p_cpp_class(s): - pass + attributes = attributes) diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index f01b5174..b8da6570 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -91,6 +91,7 @@ class PyrexType(BaseType): is_null_ptr = 0 is_cfunction = 0 is_struct_or_union = 0 + is_cpp_class = 0 is_struct = 0 is_enum = 0 is_typedef = 0 @@ -1342,6 +1343,57 @@ class CStructOrUnionType(CType): for x in self.scope.var_entries] return max(child_depths) + 1 +class CppClassType(CType): + # name string + # cname string + # kind string "cppclass" + # scope CppClassScope + # typedef_flag boolean + # packed boolean + + is_cpp_class = 1 + has_attributes = 1 + base_classes = [] + namespace = None + + def __init__(self, name, kind, scope, typedef_flag, cname, base_classes, + namespace = None, packed=False): + self.name = name + self.cname = cname + self.kind = kind + self.scope = scope + self.typedef_flag = typedef_flag + self.exception_check = True + self._convert_code = None + self.packed = packed + self.base_classes = base_classes + self.namespace = namespace + + def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0): + inherited = "" + for base_class in self.base_classes: + if inherited != "": + inherited += " : public " + inherited += base_class + if base_class != baseclasses[-1]: + inherited += " , " + return "%s%s" % (self.name, inherited) + + + def is_subclass(self, other_type): + if not base_classes.empty(): + for base_class in self.base_classes: + if base_class.is_subclass(other_type): + return 1 + return 0 + + def assignable_from_resolved_type(self, other_type): + if self.same_as_resolved_type(other_type): + return 1 + if self.is_subclass(other) or self.same_as(other_type): + return 1 + return 0 + class CEnumType(CType): # name string # cname string or None diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 76448f55..a3430d6e 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -384,6 +384,32 @@ class Scope(object): self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos) return entry + def declare_cpp_class(self, name, kind, scope, + typedef_flag, pos, cname = None, base_classes = [], namespace = None, + visibility = 'extern', packed = False): + if visibility != 'extern': + error(pos, "C++ classes may only be extern") + if not entry: + type = PyrexTypes.CppClassType( + name, kind, scope, typedef_flag, cname, base_classes, namespace, packed) + entry = self.declare_type(name, type, pos, cname, + visibility = visibility, defining = scope is not None) + self.sue_entries.append(entry) + else: + if not (entry.is_type and entry.type.is_cpp_class + and entry.type.kind == kind): + warning(pos, "'%s' redeclared " % name, 0) + elif scope and entry.type.scope: + warning(pos, "'%s' already defined (ignoring second definition)" % name, 0) + else: + self.check_previous_typedef_flag(entry, typedef_flag, pos) + if scope: + entry.type.scope = scope + self.type_entries.append(entry) + if not scope and not entry.type.scope: + self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos) + return entry + def check_previous_typedef_flag(self, entry, typedef_flag, pos): if typedef_flag != entry.type.typedef_flag: error(pos, "'%s' previously declared using '%s'" % (