diff --git a/direct/src/ffi/FFIInterrogateDatabase.py b/direct/src/ffi/FFIInterrogateDatabase.py index f1c47fd146..c62b29e93e 100644 --- a/direct/src/ffi/FFIInterrogateDatabase.py +++ b/direct/src/ffi/FFIInterrogateDatabase.py @@ -13,7 +13,7 @@ import FFISpecs import FFIRename import FFIConstants import FFIOverload - +from PythonUtil import * # FFIConstants.notify.setDebug(1) FFIConstants.notify.info('Importing interrogate library: ' + FFIConstants.InterrogateModuleName) @@ -622,35 +622,6 @@ class FFIInterrogateDatabase: newGlob = self.constructGlobalFunction(funcIndex) if 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): numGlobals = interrogate_number_of_globals() @@ -660,7 +631,6 @@ class FFIInterrogateDatabase: if newGlob: self.environment.addGlobalValue(newGlob) - def constructManifest(self, manifestIndex): descriptor = None intValue = None @@ -757,6 +727,18 @@ class FFIInterrogateDatabase: # Output all the imports based on this list of functions 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...') for type in self.environment.globalValues: type.generateGlobalCode(globalFile) diff --git a/direct/src/ffi/FFIOverload.py b/direct/src/ffi/FFIOverload.py index df2faad55d..4694292d8e 100644 --- a/direct/src/ffi/FFIOverload.py +++ b/direct/src/ffi/FFIOverload.py @@ -21,6 +21,25 @@ AT_char = 5 AT_void = 6 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): """ 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 # they are not really constructors, they are instance methods that fill # in the this pointer. + # Global functions do not need static versions if (self.methodSpecList[0].isStatic() and (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: indent(file, nesting+1, 'def ' + self.methodSpecList[0].name + '(self, *_args):\n') @@ -180,7 +200,8 @@ class FFIMethodArgumentTreeCollection: # in the this pointer. 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) indent(file, nesting+1, '\n') @@ -216,7 +237,7 @@ class FFIMethodArgumentTreeCollection: else: indent(file, nesting+2, 'elif (numArgs == ' + `numArgs` + '):\n') 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 # it must have had the wrong number or type of arguments @@ -278,7 +299,7 @@ class FFIMethodArgumentTree: # This subtree has no method spec self.tree[typeDesc] = [subTree, None] - def traverse(self, file, level=1): + def traverse(self, file, nesting, level): oneTreeHasArgs = 0 typeNameList = [] # Make a copy of the keys so we can sort them in place @@ -291,7 +312,7 @@ class FFIMethodArgumentTree: if (typeDesc == 0): # Output the function methodSpec = self.tree[0][1] - indent(file, level+2, 'return ') + indent(file, nesting+2, 'return ') methodSpec.outputOverloadedCall(file, self.classTypeDesc, 0) else: # Specify that at least one of these trees had arguments @@ -300,32 +321,32 @@ class FFIMethodArgumentTree: typeName = getTypeName(self.classTypeDesc, typeDesc) typeNameList.append(typeName) if (i == 0): - indent(file, level+2, 'if (isinstance(_args[' + `level-1` + '], ' + indent(file, nesting+2, 'if (isinstance(_args[' + `level` + '], ' + typeName + '))') else: - indent(file, level+2, 'elif (isinstance(_args[' + `level-1` + '], ' + indent(file, nesting+2, 'elif (isinstance(_args[' + `level` + '], ' + typeName + '))') # If it is looking for a float, make it accept an integer too if (typeName == 'types.FloatType'): - file.write(' or (isinstance(_args[' + `level-1` + '], ' + file.write(' or (isinstance(_args[' + `level` + '], ' + 'types.IntType' + '))') file.write(':\n') # Get to the bottom of this chain 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: # Output the function 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) # Output an else clause if one of the trees had arguments 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: indent(file, 0, ('<' + name + '> ')) indent(file, 0, "'\n") diff --git a/direct/src/ffi/FFISpecs.py b/direct/src/ffi/FFISpecs.py index 3adb31dbd1..e1d10c3dda 100644 --- a/direct/src/ffi/FFISpecs.py +++ b/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 - """ - 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') + If classTypeDesc is None, then this is a global function and should + output code as such + """ + 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: + indent(file, 0, self.getFinalName() + '(') + for i in range(numArgs): + file.write('_args[' + `i` + ']') + if (i != (numArgs - 1)): + file.write(', ') + file.write(')\n') + class GlobalFunctionSpecification(FunctionSpecification): def __init__(self): diff --git a/direct/src/ffi/FFITypes.py b/direct/src/ffi/FFITypes.py index 93cf635937..b82c6ec167 100644 --- a/direct/src/ffi/FFITypes.py +++ b/direct/src/ffi/FFITypes.py @@ -338,37 +338,10 @@ class ClassTypeDescriptor(BaseTypeDescriptor): def cullOverloadedMethods(self): """ Find all the entries that have multiple indexes for the same method name - Get rid of all others. + Get rid of all others. Do this for class methods and instance methods """ - 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 + self.overloadedClassMethods = FFIOverload.cullOverloadedMethods(self.overloadedClassMethods) + self.overloadedInstanceMethods = FFIOverload.cullOverloadedMethods(self.overloadedInstanceMethods) def filterOutStaticMethods(self): """