diff options
| author | Robert Bradshaw <robertwb@gmail.com> | 2014-01-16 00:05:44 -0800 |
|---|---|---|
| committer | Robert Bradshaw <robertwb@gmail.com> | 2014-01-16 00:05:44 -0800 |
| commit | 2108d1aa6f586445f00961bc3de1947349f7ca2b (patch) | |
| tree | fb34a596e93b429e73732337a8c24b8e306422d5 | |
| parent | d929ac0889b93703b704460bcff7433a93b8f0f4 (diff) | |
| download | cython-2108d1aa6f586445f00961bc3de1947349f7ca2b.tar.gz | |
Completely re-do out-of-order class declarations.
| -rw-r--r-- | Cython/Compiler/Nodes.py | 42 | ||||
| -rw-r--r-- | Cython/Compiler/PyrexTypes.py | 2 |
2 files changed, 12 insertions, 32 deletions
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 448530fd9..1cde9cbee 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -379,38 +379,7 @@ class StatListNode(Node): def analyse_declarations(self, env): #print "StatListNode.analyse_declarations" ### - base_classes = {} - def flatten(stats): - # Common case is trivial flatten. - if not [stat for stat in stats if isinstance(stat, StatListNode)]: - return stats - else: - all = [] - for stat in stats: - if isinstance(stat, StatListNode): - all.extend(flatten(stat.stats)) - else: - all.append(stat) - return all - flattened = flatten(self.stats) - for stat in flattened: - if isinstance(stat, CClassDefNode) and not stat.base_class_module: - base_classes[stat.class_name] = stat.base_class_name - @cached_function - def depth(class_name): - base_class = base_classes.get(class_name) - if class_name is None: - return 0 - else: - return depth(base_class) + 1 - keyed_stats = [] - for ix, stat in enumerate(flattened): - if isinstance(stat, CClassDefNode): - key = 20, depth(stat.class_name), ix - else: - key = 10, ix - keyed_stats.append((key, stat)) - for key, stat in sorted(keyed_stats): + for stat in self.stats: stat.analyse_declarations(env) def analyse_expressions(self, env): @@ -4337,6 +4306,12 @@ class CClassDefNode(ClassDefNode): warning(self.pos, "freelists cannot be used on subtypes, only the base class can manage them", 1) has_body = self.body is not None + if has_body and self.base_type and not self.base_type.scope: + # To properly initialize inherited attributes, the base type must + # be analysed before this type. + self.base_type.defered_declarations.append(lambda : self.analyse_declarations(env)) + return + if self.module_name and self.visibility != 'extern': module_path = self.module_name.split(".") home_scope = env.find_imported_module(module_path, self.pos) @@ -4385,6 +4360,9 @@ class CClassDefNode(ClassDefNode): scope.implemented = 1 env.allocate_vtable_names(self.entry) + for thunk in self.entry.type.defered_declarations: + thunk() + def analyse_expressions(self, env): if self.body: scope = self.entry.type.scope diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index d388a90b2..3f8e85fb5 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -1070,6 +1070,7 @@ class PyExtensionType(PyObjectType): # vtabstruct_cname string Name of C method table struct # vtabptr_cname string Name of pointer to C method table # vtable_cname string Name of C method table definition + # defered_declarations [thunk] Used to declare class hierarchies in order is_extension_type = 1 has_attributes = 1 @@ -1092,6 +1093,7 @@ class PyExtensionType(PyObjectType): self.vtabptr_cname = None self.vtable_cname = None self.is_external = is_external + self.defered_declarations = [] def set_scope(self, scope): self.scope = scope |
