Selaa lähdekoodia

*** empty log message ***

Joe Shochet 25 vuotta sitten
vanhempi
sitoutus
0084b86283
2 muutettua tiedostoa jossa 169 lisäystä ja 175 poistoa
  1. 25 66
      direct/src/ffi/FFISpecs.py
  2. 144 109
      direct/src/ffi/FFITypes.py

+ 25 - 66
direct/src/ffi/FFISpecs.py

@@ -137,11 +137,7 @@ class GlobalFunctionSpecification(FunctionSpecification):
         self.outputMethodHeader(methodClass, file, nesting)
         self.outputMethodBody(methodClass, file, nesting)
         self.outputMethodFooter(methodClass, file, nesting)
-    def generateInheritedMethodCode(self, methodClass, parentClass, file, nesting, needsDowncast):
-        self.outputInheritedMethodHeader(methodClass, parentClass, file, nesting, needsDowncast)
-        self.outputInheritedMethodBody(methodClass, parentClass, file, nesting, needsDowncast)
-        self.outputInheritedMethodFooter(methodClass, parentClass, file, nesting, needsDowncast)
-        
+
     ##################################################
     ## Global Function Code Generation
     ##################################################
@@ -217,52 +213,6 @@ class GlobalFunctionSpecification(FunctionSpecification):
     def outputMethodFooter(self, methodClass, file, nesting):
         indent(file, nesting+1, '\n')
 
-    ##################################################
-    ## Upcast Class Method Code Generation
-    ##################################################
-    def outputInheritedMethodHeader(self, methodClass, parentClass, file, nesting, needsDowncast):
-        argTypes = self.typeDescriptor.argumentTypes
-        thislessArgTypes = self.typeDescriptor.thislessArgTypes()
-        indent(file, nesting+1, 'def ' + self.getFinalName() + '(self')
-        if (len(thislessArgTypes) > 0):
-            file.write(', ')
-            for i in range(len(thislessArgTypes)):
-                file.write(thislessArgTypes[i].name)
-                if (i < (len(thislessArgTypes)-1)):
-                    file.write(', ')
-        file.write('):\n')
-
-    def outputInheritedMethodBody(self, methodClass, parentClass, file, nesting, needsDowncast):
-        # The method body will look something like
-        #     upcastSelf = self.upcastToParentClass()
-        #     returnValue = ParentClass.method(upcastSelf, arg)
-        #     returnValue.userManagesMemory = 1  (optional)
-        #     return returnValue
-        self.outputCFunctionComment(file, nesting+2)
-        argTypes = self.typeDescriptor.argumentTypes
-        thislessArgTypes = self.typeDescriptor.thislessArgTypes()
-        self.outputTypeChecking(methodClass, thislessArgTypes, file, nesting+2)
-        if self.typeDescriptor.userManagesMemory:
-            indent(file, nesting+2, 'self.userManagesMemory = 1\n')
-        indent(file, nesting+2, 'upcastSelf = self.upcast' + 'To'
-                   + parentClass.foreignTypeName + '()\n')
-        indent(file, nesting+2, 'returnValue = ' + parentClass.foreignTypeName
-                   + '.' + self.typeDescriptor.wrapperName + '(upcastSelf.this')
-        if (len(thislessArgTypes) > 0):
-            file.write(', ')
-            for i in range(len(thislessArgTypes)):
-                file.write(thislessArgTypes[i].passName())
-                if (i < (len(thislessArgTypes)-1)):
-                    file.write(', ')
-        file.write(')\n')
-        returnType = self.typeDescriptor.returnType.recursiveTypeDescriptor()
-        # Generate the return value code with no downcast instructions
-        returnType.generateReturnValueWrapper(file, self.typeDescriptor.userManagesMemory,
-                                              needsDowncast, nesting+2)
-
-    def outputInheritedMethodFooter(self, methodClass, parentClass, file, nesting, needsDowncast):
-        pass
-
 
 class MethodSpecification(FunctionSpecification):
     def __init__(self):
@@ -288,10 +238,10 @@ class MethodSpecification(FunctionSpecification):
         self.outputStaticBody(methodClass, file, nesting)
         self.outputStaticFooter(methodClass, file, nesting)
 
-    def generateInheritedMethodCode(self, methodClass, parentClass, file, nesting, needsDowncast):
-        self.outputInheritedMethodHeader(methodClass, parentClass, file, nesting, needsDowncast)
-        self.outputInheritedMethodBody(methodClass, parentClass, file, nesting, needsDowncast)
-        self.outputInheritedMethodFooter(methodClass, parentClass, file, nesting, needsDowncast)
+    def generateInheritedMethodCode(self, methodClass, parentList, file, nesting, needsDowncast):
+        self.outputInheritedMethodHeader(methodClass, parentList, file, nesting, needsDowncast)
+        self.outputInheritedMethodBody(methodClass, parentList, file, nesting, needsDowncast)
+        self.outputInheritedMethodFooter(methodClass, parentList, file, nesting, needsDowncast)
         
     def generateDowncastMethodCode(self, methodClass, file, nesting):
         # The downcast method code is just like regular code, but the
@@ -342,6 +292,7 @@ class MethodSpecification(FunctionSpecification):
         indent(file, nesting+2, 'assert(self.this != 0)\n')
         if self.typeDescriptor.userManagesMemory:
             indent(file, nesting+2, 'self.userManagesMemory = 1\n')
+
     def outputConstructorFooter(self, methodClass, file, nesting):
         indent(file, nesting+1, '\n')
 
@@ -443,20 +394,19 @@ class MethodSpecification(FunctionSpecification):
                     file.write(', ')
         file.write(')\n')
         returnType = self.typeDescriptor.returnType.recursiveTypeDescriptor()
-        returnType.generateReturnValueWrapper(file, self.typeDescriptor.userManagesMemory, 1, nesting+2)
+        returnType.generateReturnValueWrapper(file, self.typeDescriptor.userManagesMemory,
+                                              1, nesting+2)
 
     def outputStaticFooter(self, methodClass, file, nesting):
         indent(file, nesting+1, self.getFinalName() + ' = '
                    + FFIConstants.staticModuleName + '.' + FFIConstants.staticModuleName
                    + '(' + self.getFinalName() + ')\n')
-        indent(file, nesting+1, '\n')
-        
-
+        indent(file, nesting+1, '\n')        
 
     ##################################################
     ## Upcast Method Code Generation
     ##################################################
-    def outputInheritedMethodHeader(self, methodClass, parentClass, file, nesting, needsDowncast):
+    def outputInheritedMethodHeader(self, methodClass, parentList, file, nesting, needsDowncast):
         argTypes = self.typeDescriptor.argumentTypes
         thislessArgTypes = self.typeDescriptor.thislessArgTypes()
         indent(file, nesting+1, 'def ' + self.getFinalName() + '(self')
@@ -468,7 +418,7 @@ class MethodSpecification(FunctionSpecification):
                     file.write(', ')
         file.write('):\n')
 
-    def outputInheritedMethodBody(self, methodClass, parentClass, file, nesting, needsDowncast):
+    def outputInheritedMethodBody(self, methodClass, parentList, file, nesting, needsDowncast):
         # The method body will look something like
         #     upcastSelf = self.upcastToParentClass()
         #     returnValue = libpanda.method(upcastSelf.this, arg)
@@ -478,10 +428,19 @@ class MethodSpecification(FunctionSpecification):
         argTypes = self.typeDescriptor.argumentTypes
         thislessArgTypes = self.typeDescriptor.thislessArgTypes()
         self.outputTypeChecking(methodClass, thislessArgTypes, file, nesting+2)
-        indent(file, nesting+2, 'upcastSelf = self.upcast' + 'To'
-                   + parentClass.foreignTypeName + '()\n')
+        for i in range(len(parentList)):
+            # Only output the upcast call if that parent class defines it
+            parentClass = parentList[i]
+            methodName = 'upcastTo' + parentClass.foreignTypeName
+            if (i != 0):
+                childClass = parentList[i-1]
+                if childClass.hasMethodNamed(methodName):
+                    indent(file, nesting+2, 'upcastSelf = self.' + methodName + '()\n')
+            else:
+                if methodClass.hasMethodNamed(methodName):
+                    indent(file, nesting+2, 'upcastSelf = self.' + methodName + '()\n')
         indent(file, nesting+2, 'returnValue = ' + self.typeDescriptor.moduleName
-                   + '.' + self.typeDescriptor.wrapperName + '(upcastSelf.this')
+               + '.' + self.typeDescriptor.wrapperName + '(upcastSelf.this')
         if (len(thislessArgTypes) > 0):
             file.write(', ')
             for i in range(len(thislessArgTypes)):
@@ -494,8 +453,8 @@ class MethodSpecification(FunctionSpecification):
         returnType.generateReturnValueWrapper(file, self.typeDescriptor.userManagesMemory,
                                               needsDowncast, nesting+2)
 
-    def outputInheritedMethodFooter(self, methodClass, parentClass, file, nesting, needsDowncast):
-        indent(file, nesting+1, '\n')        
+    def outputInheritedMethodFooter(self, methodClass, parentList, file, nesting, needsDowncast):
+        indent(file, nesting+1, '\n')
 
 
 class GlobalValueSpecification:

+ 144 - 109
direct/src/ffi/FFITypes.py

@@ -212,10 +212,6 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         # Instance methods that had no this pointer are moved into here
         self.staticMethods = []
         
-        # Global methods that take this class as the first parameter are just
-        # stored with the class because it is more useable that way
-        self.globalMethods = []
-
         # These are dictionaries used to temporarily hold methods for
         # overloading while generating code
         self.overloadedClassMethods = {}
@@ -224,6 +220,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         # Nested typeDescriptors inside this class
         self.nestedTypes = []
 
+
     def getExtensionModuleName(self):
         """
         Return a filename for the extensions for this class
@@ -243,12 +240,10 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
             # Otherwise, it must be our first time through, do the real work
             self.CModules = []
             for method in (self.constructors + [self.destructor] + self.instanceMethods
-                           + self.upcastMethods + self.downcastMethods 
-                           + self.staticMethods + self.globalMethods):
+                           + self.upcastMethods + self.downcastMethods + self.staticMethods):
                 if method:
                     if (not (method.typeDescriptor.moduleName in self.CModules)):
                         self.CModules.append(method.typeDescriptor.moduleName)
-                        
                         # Now look at all the methods that we might inherit if we are at
                         # a multiple inheritance node and get their C modules
                         if (len(self.parentTypes) >= 2):
@@ -259,10 +254,6 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
                                 for method in parentType.upcastMethods:
                                     if (not (method.typeDescriptor.moduleName in self.CModules)):
                                         self.CModules.append(method.typeDescriptor.moduleName)
-                                for method in parentType.globalMethods:
-                                    if (not (method.typeDescriptor.moduleName in self.CModules)):
-                                        self.CModules.append(method.typeDescriptor.moduleName)
-                                        
             return self.CModules
 
 
@@ -272,51 +263,52 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         class references.
         Be careful about nested types
         """
-        moduleList = []
-
-        upcastMethods = []
-        if (len(self.parentTypes) >= 2):
-            for parentType in self.parentTypes:
-                for method in parentType.instanceMethods:
-                    upcastMethods.append(method)
-                for method in parentType.upcastMethods:
-                    upcastMethods.append(method)
-                for method in parentType.globalMethods:
-                    upcastMethods.append(method)
-                    
-        for method in (self.constructors + [self.destructor] + self.instanceMethods
-                       + self.upcastMethods + self.downcastMethods 
-                       + self.staticMethods + self.globalMethods + upcastMethods):
-            if method:
-                # Get the real return type (not derived)
-                returnType = method.typeDescriptor.returnType.recursiveTypeDescriptor()
-                if (not returnType.isNested):
-                    returnTypeName = returnType.foreignTypeName
-                    # Do not put our own module in the import list
-                    if ((returnTypeName != self.foreignTypeName) and
-                        # Do not put modules already in the list (like a set)
-                        (not (returnTypeName in moduleList))):
-                        # If this is a class (not a primitive), put it on the list
-                        if (returnType.__class__ == ClassTypeDescriptor):
-                            moduleList.append(returnTypeName)
-                        
-                # Now look at all the arguments
-                argTypes = method.typeDescriptor.argumentTypes
-                for argType in argTypes:
+        # Return type modules are cached once they are calculated so we
+        # do not have to calculate them again
+        try:
+            return self.returnTypeModules
+        except:
+            moduleList = []
+            upcastMethods = []
+            if (len(self.parentTypes) >= 2):
+                for parentType in self.parentTypes:
+                    for method in parentType.instanceMethods:
+                        upcastMethods.append(method)
+                    for method in parentType.upcastMethods:
+                        upcastMethods.append(method)
+            for method in (self.constructors + [self.destructor] + self.instanceMethods
+                           + self.upcastMethods + self.downcastMethods 
+                           + self.staticMethods + upcastMethods):
+                if method:
                     # Get the real return type (not derived)
-                    argType = argType.typeDescriptor.recursiveTypeDescriptor()
-                    if (not argType.isNested):
-                        argTypeName = argType.foreignTypeName
+                    returnType = method.typeDescriptor.returnType.recursiveTypeDescriptor()
+                    if (not returnType.isNested):
+                        returnTypeName = returnType.foreignTypeName
                         # Do not put our own module in the import list
-                        if ((argTypeName != self.foreignTypeName) and
+                        if ((returnTypeName != self.foreignTypeName) and
                             # Do not put modules already in the list (like a set)
-                            (not (argTypeName in moduleList))):
+                            (not (returnTypeName in moduleList))):
                             # If this is a class (not a primitive), put it on the list
-                            if (argType.__class__ == ClassTypeDescriptor):
-                                moduleList.append(argTypeName)
-                   
-        return moduleList
-    
+                            if (returnType.__class__ == ClassTypeDescriptor):
+                                moduleList.append(returnTypeName)
+                    # Now look at all the arguments
+                    argTypes = method.typeDescriptor.argumentTypes
+                    for argType in argTypes:
+                        # Get the real return type (not derived)
+                        argType = argType.typeDescriptor.recursiveTypeDescriptor()
+                        if (not argType.isNested):
+                            argTypeName = argType.foreignTypeName
+                            # Do not put our own module in the import list
+                            if ((argTypeName != self.foreignTypeName) and
+                                # Do not put modules already in the list (like a set)
+                                (not (argTypeName in moduleList))):
+                                # If this is a class (not a primitive), put it on the list
+                                if (argType.__class__ == ClassTypeDescriptor):
+                                    moduleList.append(argTypeName)
+            self.returnTypeModules = moduleList
+            return self.returnTypeModules
+
+
     def recordClassMethod(self, methodSpec):
         """
         Record all class methods in a 2 level dictionary so we can go
@@ -326,6 +318,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         methodList = ifAbsentPut(self.overloadedClassMethods, methodSpec.name, [])
         methodList.append(methodSpec)
     
+
     def recordInstanceMethod(self, methodSpec):
         """
         Record all instance methods in a 2 level dictionary so we can go
@@ -335,6 +328,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         methodList = ifAbsentPut(self.overloadedInstanceMethods, methodSpec.name, [])
         methodList.append(methodSpec)
 
+
     def cullOverloadedMethods(self):
         """
         Find all the entries that have multiple indexes for the same method name
@@ -343,6 +337,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         self.overloadedClassMethods = FFIOverload.cullOverloadedMethods(self.overloadedClassMethods)
         self.overloadedInstanceMethods = FFIOverload.cullOverloadedMethods(self.overloadedInstanceMethods)
 
+
     def filterOutStaticMethods(self):
         """
         Run through the list of instance methods and filter out the
@@ -361,6 +356,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
                 newInstanceMethods.append(method)
         self.instanceMethods = newInstanceMethods
 
+
     def recordOverloadedMethods(self):
         """
         Record all the methods in dictionaries based on method name
@@ -372,16 +368,75 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         for method in classMethods:
             self.recordClassMethod(method)
 
-        instanceMethods = (self.instanceMethods + self.globalMethods
-                           + self.upcastMethods + self.downcastMethods)
+        instanceMethods = (self.instanceMethods + self.upcastMethods + self.downcastMethods)
         for method in instanceMethods:
             self.recordInstanceMethod(method)
 
+
+    def hasMethodNamed(self, methodName):
+        for method in (self.constructors + [self.destructor] + self.instanceMethods
+                       + self.upcastMethods + self.downcastMethods + self.staticMethods):
+            if (method and (method.name == methodName)):
+                return 1
+        return 0
+
+
+    def copyParentMethods(self, file, nesting):
+        """
+        At multiple inheritance nodes, copy all the parent methods into
+        this class and call them after upcasting us to that class
+        """
+        if (len(self.parentTypes) >= 2):
+            indent(file, nesting+1, '\n')
+            indent(file, nesting+1, '##################################################\n')
+            indent(file, nesting+1, '#  Upcast inherited instance method wrappers     #\n')
+            indent(file, nesting+1, '##################################################\n')
+            indent(file, nesting+1, '\n')
+            for parentType in self.parentTypes:
+                parentList = [parentType]
+                self.copyParentMethodsRecursively(parentList, file, nesting)
+
+
+    def copyParentMethodsRecursively(self, parentList, file, nesting):
+        """
+        Copy all the parents instance methods
+        Do not copy functions if this class already has a function with that name
+        We need to recurse up the hierarchy copying all our parents nodes all
+        the way up the tree stopping either at the top, or at another MI node
+        that has already copied his parent's methods in
+        Note: Do not copy the downcast methods
+        """
+        parent = parentList[-1]
+        if (len(parent.parentTypes) > 0):
+            recurse = 1
+        else:
+            recurse = 0
+
+        for method in parent.instanceMethods:
+            if not self.hasMethodNamed(method.name):
+                # with downcast for all instance methods that are not themselves upcasts
+                method.generateInheritedMethodCode(self, parentList, file, nesting, 1) 
+        # Copy all the parents upcast methods so we transitively pick them up
+        for method in parent.upcastMethods:
+            if not self.hasMethodNamed(method.name):
+                # no downcast for all instance methods that are themselves upcasts
+                # that would cause an infinite loop
+                method.generateInheritedMethodCode(self, parentList, file, nesting, 0) 
+
+        # Now recurse up the heirarchy until we get to a node that is itself
+        # a multiple inheritance node and stop there because he will have already
+        # copied all his parent functions in
+        if recurse:
+            for parentType in parent.parentTypes:
+                newParentList = parentList[:]
+                newParentList.append(parentType)
+                self.copyParentMethodsRecursively(newParentList, file, nesting)
+
+
     def generateOverloadedMethods(self, file, nesting):
         """
         Generate code for all the overloaded methods of this class
         """
-
         if (len(self.overloadedClassMethods.values()) or
             len(self.overloadedInstanceMethods.values())):
             indent(file, nesting+1, '\n')
@@ -389,14 +444,13 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
             indent(file, nesting+1, '#  Overloaded methods                            #\n')
             indent(file, nesting+1, '##################################################\n')
             indent(file, nesting+1, '\n')
-        
-        for methodSpecList in self.overloadedClassMethods.values():
-            treeColl = FFIOverload.FFIMethodArgumentTreeCollection(self, methodSpecList)
-            treeColl.generateCode(file, nesting)
-        for methodSpecList in self.overloadedInstanceMethods.values():
+        # Overload all the class and instance methods
+        for methodSpecList in (self.overloadedClassMethods.values() +
+                               self.overloadedInstanceMethods.values()):
             treeColl = FFIOverload.FFIMethodArgumentTreeCollection(self, methodSpecList)
             treeColl.generateCode(file, nesting)
 
+
     def generateGlobalCode(self, dir, extensionsDir):
         """
         Generate shadow class code for this type.
@@ -414,6 +468,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         self.outputClassFooter(file)
         file.close()
 
+
     def generateCode(self, file, nesting):
         self.recordOverloadedMethods()
         self.cullOverloadedMethods()        
@@ -482,46 +537,12 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
             for method in self.downcastMethods:
                 method.generateDowncastMethodCode(self, file, nesting)
 
-        if len(self.globalMethods):
-            indent(file, nesting+1, '\n')
-            indent(file, nesting+1, '##################################################\n')
-            indent(file, nesting+1, '#  Global methods                                #\n')
-            indent(file, nesting+1, '##################################################\n')
-            indent(file, nesting+1, '\n')
-            for method in self.globalMethods:
-                method.generateMethodCode(self, file, nesting)
-
-        # At multiple inheritance nodes, copy all the parent methods into
-        # this class and call them after upcasting us to that class
-        if (len(self.parentTypes) >= 2):
-            indent(file, nesting+1, '\n')
-            indent(file, nesting+1, '##################################################\n')
-            indent(file, nesting+1, '#  Upcast inherited instance method wrappers     #\n')
-            indent(file, nesting+1, '##################################################\n')
-            indent(file, nesting+1, '\n')
-            for parentType in self.parentTypes:
-                # Copy all the parents instance methods
-                for method in parentType.instanceMethods:
-                    method.generateInheritedMethodCode(self, parentType, file, nesting, 1) # with downcast
-                # Copy all the parents upcast methods so we transitively pick them up
-                for method in parentType.upcastMethods:
-                    method.generateInheritedMethodCode(self, parentType, file, nesting, 0) # no downcast
-                # Do not copy the downcast methods
-
-        # At multiple inheritance nodes, copy all the parent methods into
-        # this class and call them after upcasting us to that class
-        if (len(self.parentTypes) >= 2):
-            indent(file, nesting+1, '\n')
-            indent(file, nesting+1, '##################################################\n')
-            indent(file, nesting+1, '#  Upcast global method wrappers                 #\n')
-            indent(file, nesting+1, '##################################################\n')
-            indent(file, nesting+1, '\n')
-            for parentType in self.parentTypes:
-                for method in parentType.globalMethods:
-                    method.generateInheritedMethodCode(self, parentType, file, nesting, 1) # with downcast
-
+        # Copy in all our parent nodes (only does work if we are an MI node)
+        self.copyParentMethods(file, nesting)
+        
         self.generateOverloadedMethods(file, nesting)
 
+
     def outputNestedTypes(self, file, nesting):
         if (len(self.nestedTypes) > 0):
             indent(file, nesting+1, '\n')
@@ -533,6 +554,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         for nestedType in self.nestedTypes:
             nestedType.generateCode(file, nesting+1)
 
+
     def copyExtensions(self, extensionsDir, file, nesting):
         """
         Copy in the extension file for this class if one exists
@@ -568,28 +590,37 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
             indent(file, 0, 'import ' + moduleName + 'Downcasts\n')
         indent(file, 0, '\n')
         indent(file, 0, 'import FFIExternalObject\n')
+
+
+    def outputImportsRecursively(self, parent, file, nesting):
+        for parentType in parent.parentTypes:
+            self.outputImportsRecursively(parentType, file, nesting)
+        indent(file, nesting, 'import ' + parent.foreignTypeName + '\n')
         
+        returnTypeModules = parent.getReturnTypeModules()
+        if len(returnTypeModules):
+            for moduleName in returnTypeModules:
+                indent(file, nesting, 'import ' + moduleName + '\n')
         
+
     def outputImports(self, file, nesting):
         """
         Generate code that imports the modules we need for this class
         """
+        indent(file, nesting, '# Import everybody we inherit from\n')
+        indent(file, nesting, '# and all the shadow class modules this class uses\n')
 
-        if len(self.parentTypes):
-            indent(file, nesting, '# Import everybody we inherit from\n')
-            for parent in self.parentTypes:
-                indent(file, nesting, 'import ' + parent.foreignTypeName + '\n')
-            indent(file, nesting, '\n')
-
+        # Output all of our return types
         returnTypeModules = self.getReturnTypeModules()
         if len(returnTypeModules):
-            indent(file, nesting, '# Import all the shadow class modules this class uses\n')
             for moduleName in returnTypeModules:
                 indent(file, nesting, 'import ' + moduleName + '\n')
-            
-        # an extra line just for spacing
+       
+        for parentType in self.parentTypes:
+            self.outputImportsRecursively(parentType, file, nesting)
         indent(file, nesting, '\n')
 
+
     def outputClassComment(self, file, nesting):
         """
         Output the class comment to the file
@@ -660,6 +691,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
     def outputClassFooter(self, file):
         indent(file, 0, " # When this class gets defined, put it in this module's namespace\n")
         indent(file, 0, " globals()['" + self.foreignTypeName + "'] = " + self.foreignTypeName + '\n')
+
     
     def outputBaseConstructor(self, file, nesting):
         """
@@ -681,6 +713,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         indent(file, nesting+2, 'apply(self.constructor, _args)\n')
         indent(file, nesting+2, '\n')
 
+
     def outputEmptyConstructor(self, file, nesting):
         """
         If there is no C++ constructor, we output code for a runtime error
@@ -689,6 +722,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         indent(file, nesting+1, 'def constructor(self):\n')
         indent(file, nesting+2, "raise RuntimeError, 'No C++ constructor defined for class: ' + self.__class__.__name__\n")
 
+
     def outputBaseDestructor(self, file, nesting):
         """
         This destructor overwrites the builtin Python destructor
@@ -711,6 +745,7 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         indent(file, nesting+2, 'if (self.userManagesMemory and (self.this != 0)):\n')
         indent(file, nesting+3, 'self.destructor()\n')
 
+
     def outputEmptyDestructor(self, file, nesting):
         """
         If there is no C++ destructor, we just output this
@@ -719,8 +754,8 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
         indent(file, nesting+1, 'def destructor(self):\n')
         indent(file, nesting+2, 'pass\n')
 
-    def generateReturnValueWrapper(self, file, userManagesMemory,
-                                   needsDowncast, nesting):
+
+    def generateReturnValueWrapper(self, file, userManagesMemory, needsDowncast, nesting):
         """
         Generate code that creates a shadow object of this type
         then sets the this pointer and returns the object. We call the