optimizations to overloaded functions

This commit is contained in:
Joe Shochet 2004-08-24 08:51:51 +00:00
parent 138daf587b
commit b8613bcccb
2 changed files with 67 additions and 35 deletions

View File

@ -341,20 +341,49 @@ class FFIMethodArgumentTree:
def traverse(self, file, nesting, level): def traverse(self, file, nesting, level):
oneTreeHasArgs = 0 oneTreeHasArgs = 0
typeNameList = [] typeNameList = []
# First see if this tree branches at all. If it does not there are
# drastic optimizations we can take because we can simply call the
# bottom-most function. We are not checking the types of all the
# arguments for the sake of type checking, we are simply trying to
# figure out which overloaded function to call. If there is only
# one overloaded function with this number of arguements at this
# level, it must be the one. No need to continue checking all the
# arguments.
branches = 0
subTree = self
prevTree = subTree
levelCopy = level
while subTree:
if (len(subTree.tree.keys()) == 0):
# Dead end branch
break
if (len(subTree.tree.keys()) > 1):
# Ok, we branch, it was worth a try though
branches = 1
break
prevTree = subTree
# Must only have one subtree, traverse it
subTree = subTree.tree.values()[0][0]
levelCopy += 1
# If there were no branches, this is easy
# Just output the function and return
# Note this operates on prevTree because subTree went one too far
if not branches:
methodSpec = prevTree.tree.values()[0][1]
indent(file, nesting+2, 'return ')
methodSpec.outputOverloadedCall(file, prevTree.classTypeDesc, levelCopy)
return
# Ok, We must have a branch down here somewhere
# 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
sortedKeys = self.tree.keys() sortedKeys = self.tree.keys()
# Sort the keys based on inheritance hierarchy, most specific classes first # Sort the keys based on inheritance hierarchy, most specific classes first
sortedKeys.sort(subclass) sortedKeys.sort(subclass)
# Import everybody we need
for i in range(len(sortedKeys)):
typeDesc = sortedKeys[i]
if ((typeDesc != 0) and
(not typeDesc.isNested) and
# Do not put our own module in the import list
(self.classTypeDesc != typeDesc) and
# If this is a class (not a primitive), put it on the list
(typeDesc.__class__ == FFITypes.ClassTypeDescriptor)):
indent(file, nesting+2, 'import ' + typeDesc.foreignTypeName + '\n')
for i in range(len(sortedKeys)): for i in range(len(sortedKeys)):
typeDesc = sortedKeys[i] typeDesc = sortedKeys[i]
# See if this takes no arguments # See if this takes no arguments
@ -364,6 +393,15 @@ class FFIMethodArgumentTree:
indent(file, nesting+2, 'return ') indent(file, nesting+2, 'return ')
methodSpec.outputOverloadedCall(file, self.classTypeDesc, 0) methodSpec.outputOverloadedCall(file, self.classTypeDesc, 0)
else: else:
# Import a file if we need to for this typeDesc
if ((typeDesc != 0) and
(not typeDesc.isNested) and
# Do not put our own module in the import list
(self.classTypeDesc != typeDesc) and
# If this is a class (not a primitive), put it on the list
(typeDesc.__class__ == FFITypes.ClassTypeDescriptor)):
indent(file, nesting+2, 'import ' + typeDesc.foreignTypeName + '\n')
# Specify that at least one of these trees had arguments # Specify that at least one of these trees had arguments
# so we know to output an else clause # so we know to output an else clause
oneTreeHasArgs = 1 oneTreeHasArgs = 1
@ -384,23 +422,19 @@ class FFIMethodArgumentTree:
+ 'types.IntType' + 'types.IntType'
+ '))') + '))')
if (i == 0):
indent(file, nesting+2, 'if ' + condition + ':\n') indent(file, nesting+2, 'if ' + condition + ':\n')
else:
indent(file, nesting+2, 'elif ' + condition + ':\n') if (self.tree[typeDesc][0] is not None):
# Get to the bottom of this chain
if (self.tree[typeDesc][0] != None):
self.tree[typeDesc][0].traverse(file, nesting+1, level+1) self.tree[typeDesc][0].traverse(file, nesting+1, level+1)
else: else:
# Output the function
methodSpec = self.tree[typeDesc][1] methodSpec = self.tree[typeDesc][1]
indent(file, nesting+3, 'return ') indent(file, nesting+3, 'return ')
numArgs = level+1 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, nesting+2, 'else:\n') indent(file, nesting+2, "raise TypeError, 'Invalid argument " + `level` + ", expected one of: ")
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")

View File

@ -101,9 +101,9 @@ class FunctionSpecification:
""" """
Write the function call to call this overloaded method Write the function call to call this overloaded method
For example: For example:
self.overloaded_setPos_ptrNodePath_float_float_float(_args[0], _args[1], _args[2]) self.overloaded_setPos_ptrNodePath_float_float_float(*_args)
If it is a class (static) method, call the class method If it is a class (static) method, call the class method
Class.overloaded_setPos_ptrNodePath_float_float_float(_args[0], _args[1], _args[2]) Class.overloaded_setPos_ptrNodePath_float_float_float(*_args)
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
@ -117,22 +117,20 @@ class FunctionSpecification:
""" """
if classTypeDesc: if classTypeDesc:
if (self.isStatic() and not self.isConstructor()): if (self.isStatic() and not self.isConstructor()):
indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '(') if numArgs:
indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '(*_args)\n')
else: else:
indent(file, 0, 'self.' + self.getFinalName() + '(') indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '()\n')
for i in range(numArgs):
file.write('_args[' + `i` + ']')
if (i != (numArgs - 1)):
file.write(', ')
file.write(')\n')
else: else:
indent(file, 0, self.getFinalName() + '(') if numArgs:
for i in range(numArgs): indent(file, 0, 'self.' + self.getFinalName() + '(*_args)\n')
file.write('_args[' + `i` + ']') else:
if (i != (numArgs - 1)): indent(file, 0, 'self.' + self.getFinalName() + '()\n')
file.write(', ') else:
file.write(')\n') if numArgs:
indent(file, 0, self.getFinalName() + '(*_args)\n')
else:
indent(file, 0, self.getFinalName() + '()\n')
class GlobalFunctionSpecification(FunctionSpecification): class GlobalFunctionSpecification(FunctionSpecification):