Joe Shochet пре 25 година
родитељ
комит
76a8f5abac

+ 13 - 31
direct/src/ffi/FFIInterrogateDatabase.py

@@ -13,7 +13,7 @@ import FFISpecs
 import FFIRename
 import FFIRename
 import FFIConstants
 import FFIConstants
 import FFIOverload
 import FFIOverload
-
+from PythonUtil import *
 
 
 # FFIConstants.notify.setDebug(1)
 # FFIConstants.notify.setDebug(1)
 FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.InterrogateModuleName)
 FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.InterrogateModuleName)
@@ -622,35 +622,6 @@ class FFIInterrogateDatabase:
                 newGlob = self.constructGlobalFunction(funcIndex)
                 newGlob = self.constructGlobalFunction(funcIndex)
                 if newGlob:
                 if newGlob:
                     self.environment.addGlobalFunction(newGlob)
                     self.environment.addGlobalFunction(newGlob)
-
-        """
-        # Take all the global functions that have a Panda Class as their
-        # first argument and make them class methods on that class
-        # For example the global function
-        #    get_distance(node1, node2)
-        # becomes:
-        #    node1.getDistance(node2)
-
-        # Functions that do not get moved will be stored here temporarily
-        tempGlobalFunctions = []
-        for funcSpec in self.environment.globalFunctions:
-            # If there are any arguments
-            if (len(funcSpec.typeDescriptor.argumentTypes) > 0):
-                # If the first argument is a class type descriptor
-                methodArgSpec = funcSpec.typeDescriptor.argumentTypes[0]
-                argBaseType = methodArgSpec.typeDescriptor.recursiveTypeDescriptor()
-                if isinstance(argBaseType, FFITypes.ClassTypeDescriptor):
-                    # Move this global function into the class
-                    argBaseType.globalMethods.append(funcSpec)
-                else:
-                    # Copy this function into the temp list
-                    tempGlobalFunctions.append(funcSpec)
-            else:
-                # Copy this function into the temp list
-                tempGlobalFunctions.append(funcSpec)
-        # Copy the temp list back over the real list
-        self.environment.globalFunctions = tempGlobalFunctions
-        """
                     
                     
     def addGlobalValues(self, CModuleName):
     def addGlobalValues(self, CModuleName):
         numGlobals = interrogate_number_of_globals()
         numGlobals = interrogate_number_of_globals()
@@ -660,7 +631,6 @@ class FFIInterrogateDatabase:
             if newGlob:
             if newGlob:
                 self.environment.addGlobalValue(newGlob)
                 self.environment.addGlobalValue(newGlob)
 
 
-
     def constructManifest(self, manifestIndex):
     def constructManifest(self, manifestIndex):
         descriptor = None
         descriptor = None
         intValue = None
         intValue = None
@@ -757,6 +727,18 @@ class FFIInterrogateDatabase:
         # Output all the imports based on this list of functions
         # Output all the imports based on this list of functions
         outputGlobalFileImports(globalFile, globalFunctions, CModuleName)
         outputGlobalFileImports(globalFile, globalFunctions, CModuleName)
 
 
+        # Generate overloading
+        overloadedGlobalFunctions = {}
+        for methodSpec in globalFunctions:
+            methodList = ifAbsentPut(overloadedGlobalFunctions, methodSpec.name, [])
+            methodList.append(methodSpec)
+
+        overloadedGlobalFunctions = FFIOverload.cullOverloadedMethods(overloadedGlobalFunctions)
+
+        for methodSpecList in overloadedGlobalFunctions.values():
+            treeColl = FFIOverload.FFIMethodArgumentTreeCollection(None, methodSpecList)
+            treeColl.generateCode(globalFile, -1)
+
         FFIConstants.notify.info( 'Generating global value code...')
         FFIConstants.notify.info( 'Generating global value code...')
         for type in self.environment.globalValues:
         for type in self.environment.globalValues:
             type.generateGlobalCode(globalFile)
             type.generateGlobalCode(globalFile)

+ 35 - 14
direct/src/ffi/FFIOverload.py

@@ -21,6 +21,25 @@ AT_char = 5
 AT_void = 6
 AT_void = 6
 AT_string = 7
 AT_string = 7
 
 
+def cullOverloadedMethods(fullMethodDict):
+    """
+    Find all the entries that have multiple indexes for the same method name
+    Get rid of all others.
+    """
+    tmpDict = {}
+    # For each class
+    for methodName in fullMethodDict.keys():
+        methodList = fullMethodDict[methodName]
+        # See if this method has more than one function index (overloaded)
+        if (len(methodList) > 1):
+            tmpDict[methodName] = methodList
+            # Mark all the method specifications as overloaded
+            for methodSpec in methodList:
+                methodSpec.overloaded = 1
+
+    return tmpDict
+
+
 def getTypeName(classTypeDesc, typeDesc):
 def getTypeName(classTypeDesc, typeDesc):
     """
     """
     Map the interrogate primitive type names to python type names.
     Map the interrogate primitive type names to python type names.
@@ -161,10 +180,11 @@ class FFIMethodArgumentTreeCollection:
         # Constructors are not treated as static. They are special because
         # Constructors are not treated as static. They are special because
         # they are not really constructors, they are instance methods that fill
         # they are not really constructors, they are instance methods that fill
         # in the this pointer.
         # in the this pointer.
+        # Global functions do not need static versions
         if (self.methodSpecList[0].isStatic() and 
         if (self.methodSpecList[0].isStatic() and 
             (not self.methodSpecList[0].isConstructor())):
             (not self.methodSpecList[0].isConstructor())):
-                indent(file, nesting+1, 'def ' +
-                       self.methodSpecList[0].name + '(*_args):\n')
+            indent(file, nesting+1, 'def ' +
+                   self.methodSpecList[0].name + '(*_args):\n')
         else:
         else:
             indent(file, nesting+1, 'def ' +
             indent(file, nesting+1, 'def ' +
                    self.methodSpecList[0].name + '(self, *_args):\n')
                    self.methodSpecList[0].name + '(self, *_args):\n')
@@ -180,7 +200,8 @@ class FFIMethodArgumentTreeCollection:
         # in the this pointer.
         # in the this pointer.
 
 
         if (self.methodSpecList[0].isStatic() and
         if (self.methodSpecList[0].isStatic() and
-            (not self.methodSpecList[0].isConstructor())):
+            (not self.methodSpecList[0].isConstructor()) and
+            (not isinstance(self.methodSpecList[0], FFISpecs.GlobalFunctionSpecification))):
                 self.outputOverloadedStaticFooter(file, nesting)
                 self.outputOverloadedStaticFooter(file, nesting)
         indent(file, nesting+1, '\n')
         indent(file, nesting+1, '\n')
 
 
@@ -216,7 +237,7 @@ class FFIMethodArgumentTreeCollection:
                 else:
                 else:
                     indent(file, nesting+2, 'elif (numArgs == ' + `numArgs` + '):\n')
                     indent(file, nesting+2, 'elif (numArgs == ' + `numArgs` + '):\n')
                 tree.setup()
                 tree.setup()
-                tree.traverse(file, nesting+1)
+                tree.traverse(file, nesting+1, 0)
 
 
         # If the overloaded function got all the way through the if statements
         # If the overloaded function got all the way through the if statements
         # it must have had the wrong number or type of arguments
         # it must have had the wrong number or type of arguments
@@ -278,7 +299,7 @@ class FFIMethodArgumentTree:
                     # This subtree has no method spec
                     # This subtree has no method spec
                     self.tree[typeDesc] = [subTree, None]
                     self.tree[typeDesc] = [subTree, None]
 
 
-    def traverse(self, file, level=1):
+    def traverse(self, file, nesting, level):
         oneTreeHasArgs = 0
         oneTreeHasArgs = 0
         typeNameList = []
         typeNameList = []
         # Make a copy of the keys so we can sort them in place
         # Make a copy of the keys so we can sort them in place
@@ -291,7 +312,7 @@ class FFIMethodArgumentTree:
             if (typeDesc == 0):
             if (typeDesc == 0):
                 # Output the function
                 # Output the function
                 methodSpec = self.tree[0][1]
                 methodSpec = self.tree[0][1]
-                indent(file, level+2, 'return ')
+                indent(file, nesting+2, 'return ')
                 methodSpec.outputOverloadedCall(file, self.classTypeDesc, 0)
                 methodSpec.outputOverloadedCall(file, self.classTypeDesc, 0)
             else:
             else:
                 # Specify that at least one of these trees had arguments
                 # Specify that at least one of these trees had arguments
@@ -300,32 +321,32 @@ class FFIMethodArgumentTree:
                 typeName = getTypeName(self.classTypeDesc, typeDesc)
                 typeName = getTypeName(self.classTypeDesc, typeDesc)
                 typeNameList.append(typeName)
                 typeNameList.append(typeName)
                 if (i == 0):
                 if (i == 0):
-                    indent(file, level+2, 'if (isinstance(_args[' + `level-1` + '], '
+                    indent(file, nesting+2, 'if (isinstance(_args[' + `level` + '], '
                            + typeName
                            + typeName
                            + '))')
                            + '))')
                 else:
                 else:
-                    indent(file, level+2, 'elif (isinstance(_args[' + `level-1` + '], '
+                    indent(file, nesting+2, 'elif (isinstance(_args[' + `level` + '], '
                            + typeName
                            + typeName
                            + '))')                    
                            + '))')                    
                 # If it is looking for a float, make it accept an integer too
                 # If it is looking for a float, make it accept an integer too
                 if (typeName == 'types.FloatType'):
                 if (typeName == 'types.FloatType'):
-                    file.write(' or (isinstance(_args[' + `level-1` + '], '
+                    file.write(' or (isinstance(_args[' + `level` + '], '
                                + 'types.IntType'
                                + 'types.IntType'
                                + '))')
                                + '))')
                 file.write(':\n')
                 file.write(':\n')
                 # Get to the bottom of this chain
                 # Get to the bottom of this chain
                 if (self.tree[typeDesc][0] != None):
                 if (self.tree[typeDesc][0] != None):
-                    self.tree[typeDesc][0].traverse(file, level+1)
+                    self.tree[typeDesc][0].traverse(file, nesting+1, level+1)
                 else:
                 else:
                     # Output the function
                     # Output the function
                     methodSpec = self.tree[typeDesc][1]
                     methodSpec = self.tree[typeDesc][1]
-                    indent(file, level+3, 'return ')
-                    numArgs = level
+                    indent(file, nesting+3, 'return ')
+                    numArgs = level+1
                     methodSpec.outputOverloadedCall(file, self.classTypeDesc, numArgs)
                     methodSpec.outputOverloadedCall(file, self.classTypeDesc, numArgs)
         # Output an else clause if one of the trees had arguments
         # Output an else clause if one of the trees had arguments
         if oneTreeHasArgs:
         if oneTreeHasArgs:
-            indent(file, level+2, 'else:\n')
-            indent(file, level+3, "raise TypeError, 'Invalid argument " + `level-1` + ", expected one of: ")
+            indent(file, nesting+2, 'else:\n')
+            indent(file, nesting+3, "raise TypeError, 'Invalid argument " + `level` + ", expected one of: ")
             for name in typeNameList:
             for name in typeNameList:
                 indent(file, 0, ('<' + name + '> '))
                 indent(file, 0, ('<' + name + '> '))
             indent(file, 0, "'\n")
             indent(file, 0, "'\n")

+ 20 - 9
direct/src/ffi/FFISpecs.py

@@ -99,18 +99,29 @@ class FunctionSpecification:
           
           
         These do not get indented because they are not the beginning of the line
         These do not get indented because they are not the beginning of the line
 
 
+        If classTypeDesc is None, then this is a global function and should
+        output code as such
+
         """
         """
-        if (self.isStatic() and not self.isConstructor()):
-            indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '(')
+        if classTypeDesc:
+            if (self.isStatic() and not self.isConstructor()):
+                indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '(')
+            else:
+                indent(file, 0, 'self.' + self.getFinalName() + '(')
+
+            for i in range(numArgs):
+                file.write('_args[' + `i` + ']')
+                if (i != (numArgs - 1)):
+                    file.write(', ')
+            file.write(')\n')
         else:
         else:
-            indent(file, 0, 'self.' + self.getFinalName() + '(')
+            indent(file, 0, self.getFinalName() + '(')
+            for i in range(numArgs):
+                file.write('_args[' + `i` + ']')
+                if (i != (numArgs - 1)):
+                    file.write(', ')
+            file.write(')\n')
             
             
-        for i in range(numArgs):
-            file.write('_args[' + `i` + ']')
-            if (i != (numArgs - 1)):
-                file.write(', ')
-        file.write(')\n')
-
 
 
 class GlobalFunctionSpecification(FunctionSpecification):
 class GlobalFunctionSpecification(FunctionSpecification):
     def __init__(self):
     def __init__(self):

+ 4 - 31
direct/src/ffi/FFITypes.py

@@ -338,37 +338,10 @@ class ClassTypeDescriptor(BaseTypeDescriptor):
     def cullOverloadedMethods(self):
     def cullOverloadedMethods(self):
         """
         """
         Find all the entries that have multiple indexes for the same method name
         Find all the entries that have multiple indexes for the same method name
-        Get rid of all others.
-        """
-        tmpDict = {}
-        # For each class
-        for methodName in self.overloadedClassMethods.keys():
-            methodList = self.overloadedClassMethods[methodName]
-            # See if this method has more than one function index (overloaded)
-            if (len(methodList) > 1):
-                tmpDict[methodName] = methodList
-                # Mark all the method specifications as overloaded
-                for methodSpec in methodList:
-                    methodSpec.overloaded = 1
-        
-        # Now we are done. Jam the tmpDict into the real one
-        self.overloadedClassMethods = tmpDict
-        
-        # Now do the same for instance methods
-        tmpDict = {}
-        # For each class
-        for methodName in self.overloadedInstanceMethods.keys():
-            methodList = self.overloadedInstanceMethods[methodName]
-            # See if this method has more than one function index (overloaded)
-            if (len(methodList) > 1):
-                # Copy over the method list
-                tmpDict[methodName] = methodList
-                # Mark all the method specifications as overloaded
-                for methodSpec in methodList:
-                    methodSpec.overloaded = 1
-        
-        # Now we are done. Jam the tmpDict into the real one
-        self.overloadedInstanceMethods = tmpDict
+        Get rid of all others. Do this for class methods and instance methods
+        """
+        self.overloadedClassMethods = FFIOverload.cullOverloadedMethods(self.overloadedClassMethods)
+        self.overloadedInstanceMethods = FFIOverload.cullOverloadedMethods(self.overloadedInstanceMethods)
 
 
     def filterOutStaticMethods(self):
     def filterOutStaticMethods(self):
         """
         """