*** empty log message ***

This commit is contained in:
Joe Shochet 2000-11-17 22:37:18 +00:00
parent aeb400fc59
commit 0084b86283
2 changed files with 169 additions and 175 deletions

View File

@ -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:

View File

@ -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