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):
oneTreeHasArgs = 0
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
sortedKeys = self.tree.keys()
# Sort the keys based on inheritance hierarchy, most specific classes first
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)):
typeDesc = sortedKeys[i]
# See if this takes no arguments
@ -364,6 +393,15 @@ class FFIMethodArgumentTree:
indent(file, nesting+2, 'return ')
methodSpec.outputOverloadedCall(file, self.classTypeDesc, 0)
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
# so we know to output an else clause
oneTreeHasArgs = 1
@ -384,23 +422,19 @@ class FFIMethodArgumentTree:
+ 'types.IntType'
+ '))')
if (i == 0):
indent(file, nesting+2, 'if ' + condition + ':\n')
else:
indent(file, nesting+2, 'elif ' + condition + ':\n')
# Get to the bottom of this chain
if (self.tree[typeDesc][0] != None):
indent(file, nesting+2, 'if ' + condition + ':\n')
if (self.tree[typeDesc][0] is not None):
self.tree[typeDesc][0].traverse(file, nesting+1, level+1)
else:
# Output the function
methodSpec = self.tree[typeDesc][1]
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, nesting+2, 'else:\n')
indent(file, nesting+3, "raise TypeError, 'Invalid argument " + `level` + ", expected one of: ")
indent(file, nesting+2, "raise TypeError, 'Invalid argument " + `level` + ", expected one of: ")
for name in typeNameList:
indent(file, 0, ('<' + name + '> '))
indent(file, 0, "'\n")

View File

@ -101,9 +101,9 @@ class FunctionSpecification:
"""
Write the function call to call this overloaded method
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
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
they are not really constructors, they are instance methods that fill
@ -117,22 +117,20 @@ class FunctionSpecification:
"""
if classTypeDesc:
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:
indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '()\n')
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 numArgs:
indent(file, 0, 'self.' + self.getFinalName() + '(*_args)\n')
else:
indent(file, 0, 'self.' + self.getFinalName() + '()\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')
if numArgs:
indent(file, 0, self.getFinalName() + '(*_args)\n')
else:
indent(file, 0, self.getFinalName() + '()\n')
class GlobalFunctionSpecification(FunctionSpecification):