OpenADFortTk (SourceProcessing)
Canon/canon.py
Go to the documentation of this file.
00001 '''
00002 canonicalization routines
00003 '''
00004 
00005 from _Setup import *
00006 
00007 from PyUtil.debugManager import DebugManager
00008 from PyUtil.symtab import Symtab,SymtabEntry,SymtabError,globalTypeTable
00009 from PyUtil.typetab import TypetabEntry
00010 from PyUtil.argreplacement import replaceArgs
00011 
00012 from PyFort.intrinsic import is_intrinsic,getGenericName, isUsedNonStandard,getBuiltInTypes
00013 from PyFort.inference import InferenceError,expressionType,appType,isArrayReference,canonicalTypeClass,expressionShape,isSpecExpression
00014 import PyFort.flow as flow
00015 import PyFort.fortExp as fe
00016 import PyFort.fortStmts as fs
00017 import PyFort.fortUnit as fortUnit
00018 import Canon.function2subroutine as function2subroutine
00019 import Canon.subroutinizedIntrinsics as subroutinizedIntrinsics
00020 
00021 import copy
00022 import itertools
00023 
00024 _tmp_prefix   = 'oad_ctmp'
00025 
00026 class CanonError(Exception):
00027     '''exception for errors that occur during canonicalization'''
00028     _keepGoing=False
00029     
00030     @staticmethod
00031     def keepGoing():
00032         CanonError._keepGoing=True
00033 
00034     def __init__(self,msg,lineNumber):
00035         self.msg  = msg
00036         self.lineNumber = lineNumber
00037 
00038     def __str__(self):
00039         errString='\nERROR: CanonError at line '+str(self.lineNumber)+': '+str(self.msg)
00040         return (errString)
00041 
00042 class UnitCanonicalizer(object):
00043     'class to facilitate canonicalization on a per-unit basis'
00044 
00045     _hoistConstantsFlag = False
00046     _hoistStringsFlag = False
00047     _functionBlockFlag = False
00048     _createResultDeclFlag = False
00049     _keepFunctionDecl = True
00050     _subroutinizeIntegerFunctions = False
00051     
00052     _ourPassiveTypes=[fs.IntegerStmt,fs.CharacterStmt]
00053     _ourPassiveTypeIds=[getBuiltInTypes().index((fs.CharacterStmt,4)),
00054                         getBuiltInTypes().index((fs.IntegerStmt,4)),
00055                         getBuiltInTypes().index((fs.IntegerStmt,8))]
00056 
00057     @staticmethod
00058     def setHoistConstantsFlag(hoistConstantsFlag):
00059         UnitCanonicalizer._hoistConstantsFlag = hoistConstantsFlag
00060 
00061     @staticmethod
00062     def setHoistStringsFlag(hoistStringsFlag):
00063         UnitCanonicalizer._hoistStringsFlag = hoistStringsFlag
00064 
00065     @staticmethod
00066     def setFunctionBlockFlag(functionBlockFlag):
00067         UnitCanonicalizer._functionBlockFlag = functionBlockFlag
00068 
00069     @staticmethod
00070     def setCreateResultDeclFlag(createResultFlag):
00071         UnitCanonicalizer._createResultDeclFlag = createResultFlag
00072 
00073     @staticmethod
00074     def setKeepFunctionDef(keepFunctionDefFlag):
00075         UnitCanonicalizer._keepFunctionDecl = keepFunctionDefFlag
00076 
00077     @staticmethod
00078     def setSubroutinizeIntegerFunctions(flag):
00079         UnitCanonicalizer._subroutinizeIntegerFunctions = flag
00080 
00081     _overloadingMode = False
00082 
00083     @staticmethod
00084     def setOverloadingMode():
00085         UnitCanonicalizer._overloadingMode = True
00086         
00087     def __init__(self,aUnit,srModuleUsed=False):
00088         self.__myUnit = aUnit
00089         self.__myNewDecls = []
00090         self.__myNewExecs = []
00091         self.__tempCounter = 0
00092         self.__recursionDepth = 0
00093         self.__outParam = ''
00094         self.__resultDecl = None
00095         self.__processedFunctions = []
00096         self.__stmtFunctionStmts = []
00097 
00098     def shouldSubroutinizeFunction(self,theApp,parentStmt):
00099         '''
00100         A function should be subroutinized if it is an intrinsic and subroutinizedIntrinsics.shouldSubroutinize
00101         returns true or if is not an intrinsic
00102         '''
00103         DebugManager.debug('UnitCanonicalizer.shouldSubroutinizeFunction called on "'+str(theApp)+'"')
00104         if not isinstance(theApp,fe.App):
00105             raise CanonError('UnitCanonicalizer.shouldSubroutinizeFunction called on non-App object '+str(theApp),parentStmt.lineNumber)
00106         if isinstance(theApp.head,fe.Sel):
00107             return False
00108         theSymtabEntry = self.__myUnit.symtab.lookup_name(theApp.head)
00109         if theSymtabEntry: 
00110             if isinstance(theSymtabEntry.entryKind,SymtabEntry.StatementFunctionEntryKind):
00111                 return False
00112             if isinstance(theSymtabEntry.entryKind,SymtabEntry.VariableEntryKind):
00113                 raise CanonError('UnitCanonicalizer.shouldSubroutinizeFunction called on array reference '+str(theApp)+" with "+theSymtabEntry.debug(theApp.head),parentStmt.lineNumber)
00114         try:
00115             appTypeEntry = appType(theApp,self.__myUnit.symtab,parentStmt.lineNumber)
00116         except InferenceError,errorObj:
00117             DebugManager.warning("cannot determine return type and canonicalize function call; "+errorObj.msg,parentStmt.lineNumber)
00118             return False
00119         if is_intrinsic(theApp.head):
00120             if UnitCanonicalizer._overloadingMode:
00121                 return False
00122             baseType=appTypeEntry.getBaseTypeEntry()
00123             DebugManager.debug('UnitCanonicalizer.shouldSubroutinizeFunction: It\'s an intrinsic of type '+appTypeEntry.debug())
00124             return subroutinizedIntrinsics.shouldSubroutinize(theApp) and (UnitCanonicalizer._subroutinizeIntegerFunctions or not (isinstance(baseType.entryKind,TypetabEntry.BuiltInEntryKind) and (baseType.entryKind.type_name=='integer_4')))
00125         elif isinstance(appTypeEntry.entryKind,TypetabEntry.NamedTypeEntryKind):
00126             # this is an implicit initialization; do not subroutinize
00127             return False
00128         else:
00129             # need to fix for case where app.head is a type (implicit initialization)
00130             return True
00131 
00132     def __fixSpecExpression(self,theExp,lineNumber):
00133         ''' we can safely drop some slice expressions if the inquiry fynction does not refer to it '''
00134         if (isinstance(theExp,fe.App) and theExp.head.lower() in ["size","lbound","ubound"]
00135             and 
00136             len(theExp.args)==2) :
00137             dim=None
00138             if (isinstance(theExp.args[1],fe.NamedParam) and theExp.args[1].myId.lower()=="dim" and fe._int_re.match(theExp.args[1].myRHS)):
00139                 dim=int(theExp.args[1].myRHS)
00140             elif(fe._int_re.match(theExp.args[1])):
00141                 dim=int(theExp.args[1])
00142             if dim:
00143                 argDims=[]
00144                 for pos,argDim in enumerate(theExp.args[0].args):
00145                     if pos+1!=dim:
00146                         argDims.append(fe.Zslice())
00147                     else:
00148                         argDims.append(argDim)
00149                 # now replace it
00150                 theExp.args[0].args=argDims
00151 
00152     def __newTemp(self,anExpression,parentStmt):
00153         '''The new temporary variable assumes the value of anExpression'''
00154         theNewTemp = _tmp_prefix + str(self.__tempCounter)
00155         self.__tempCounter += 1
00156         expTypeEntry = expressionType(anExpression,self.__myUnit.symtab,parentStmt.lineNumber)
00157         if isinstance(expTypeEntry.entryKind,TypetabEntry.CharacterEntryKind):
00158             charLenEntry=globalTypeTable.charLenTab.lookupCharLenId(expTypeEntry.entryKind.charLenId)
00159             varTypeClass=fs.CharacterStmt
00160             typeKind=charLenEntry.getCharLenExp()
00161             varModifierList=[typeKind]
00162         else:
00163             (varTypeClass,typeKind)=globalTypeTable.intrinsicIdToTypeMap[expTypeEntry.getBaseTypeId()]
00164             varModifierList=[]
00165         varShape=expressionShape(anExpression,self.__myUnit.symtab,parentStmt.lineNumber)
00166         if isinstance(expTypeEntry.entryKind,TypetabEntry.BuiltInEntryKind) and expTypeEntry.entryKind.type_name=='real_8':
00167             print >>sys.stderr,'WARNING: Temp variable forced to 8-byte float (real -> double)'
00168         DebugManager.debug('replaced with '+str(theNewTemp)+' of type '+expTypeEntry.debug())
00169         typeAttrList=[]
00170         needsAlloc=False
00171         if varShape:
00172             declDimArgs=[]
00173             for dim in varShape:
00174                 if (not isSpecExpression(dim,self.__myUnit.symtab,parentStmt.lineNumber)):
00175                     self.__fixSpecExpression(dim,parentStmt.lineNumber)
00176                 if (not isSpecExpression(dim,self.__myUnit.symtab,parentStmt.lineNumber)):
00177                     needsAlloc=True
00178                     declDimArgs.append(fe.Zslice())
00179                 else:
00180                     declDimArgs.append(dim)
00181             typeAttrList.append(fe.App('dimension',declDimArgs))
00182         if needsAlloc:
00183             typeAttrList.append("allocatable")
00184             DebugManager.warning("temporary  "+theNewTemp+" declared as allocatable but allocation logic is as of yet not implented",parentStmt.lineNumber)
00185         theNewDecl = varTypeClass(varModifierList,typeAttrList,[theNewTemp])
00186         typeId = globalTypeTable.getType(theNewDecl,self.__myUnit.symtab)
00187         self.__myNewDecls.append(theNewDecl)
00188         self.__myUnit.symtab.enter_name(theNewTemp,
00189                                         SymtabEntry(SymtabEntry.VariableEntryKind(),
00190                                                     type=(varTypeClass,varModifierList),
00191                                                     dimensions=varShape,
00192                                                     origin='temp',
00193                                                     typetab_id=typeId))
00194         return (theNewTemp,varTypeClass,varModifierList)
00195 
00196     def __canonicalizeIntrinsicEllipsisRec(self,head,args):
00197         if (len(args)==2):
00198             return fe.App(head,args)
00199         else:
00200             return fe.App(head,[args[0],self.__canonicalizeIntrinsicEllipsisRec(head,args[1:])])
00201         
00202     def __canonicalizeFuncCall(self,theFuncCall,parentStmt):
00203         '''turn a function call into a subroutine call
00204         returns the new temp created as return value for the new subroutine call'''
00205         DebugManager.debug(self.__recursionDepth*'|\t'+'converting function call "'+str(theFuncCall)+'" to a subroutine call')
00206         self.__recursionDepth += 1
00207         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|  creating new temp for the result of the subroutine that replaces "'+str(theFuncCall)+'":',newLine=False)
00208         (theNewTemp,newTempType,newTempTypeMods) = self.__newTemp(theFuncCall,parentStmt)
00209         newArgs = [theNewTemp]
00210         newSubName=''
00211         if is_intrinsic(theFuncCall.head):
00212             funcName=getGenericName(theFuncCall.head)
00213             newSubName = subroutinizedIntrinsics.makeName(funcName)
00214             argRanks=[]
00215             for arg in theFuncCall.args:
00216                 argS=expressionShape(arg,self.__myUnit.symtab,parentStmt.lineNumber)                            
00217                 if argS:
00218                     argRanks.append(len(argS))
00219                 else:
00220                     argRanks.append(0)
00221             (d,t)=canonicalTypeClass(newTempType,newTempTypeMods)
00222             if (d):
00223                 subroutinizedIntrinsics.markRequired(funcName,t,argRanks)
00224             else:
00225                 for t in subroutinizedIntrinsics.typeList:
00226                     subroutinizedIntrinsics.markRequired(funcName,t,argRanks)
00227             if funcName in ('max','min') and len(theFuncCall.args)>2 :
00228                 self.__recursionDepth -= 1
00229                 return self.__canonicalizeFuncCall(self.__canonicalizeIntrinsicEllipsisRec(theFuncCall.head,theFuncCall.args),parentStmt)
00230         else:
00231             newSubName = subroutinizedIntrinsics.call_prefix + theFuncCall.head
00232         self.__myNewExecs.append(self.__canonicalizeSubCallStmt(\
00233             fs.CallStmt(newSubName,
00234                         theFuncCall.args+newArgs,
00235                         lineNumber=parentStmt.lineNumber,
00236                         label=False,
00237                         lead=parentStmt.lead)))
00238         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00239         self.__recursionDepth -= 1
00240         return theNewTemp
00241 
00242     def __hoistExpression(self,theExpression,parentStmt,paramName,forceIt=False):
00243         # function calls that are to be turned into subroutine calls
00244         # -> return the temp that carries the value for the new subcall
00245         # or alternatively if paramName is set return the construct
00246         # for a named parameter expression
00247         if isinstance(theExpression,fe.App) and \
00248            not isArrayReference(theExpression,self.__myUnit.symtab,parentStmt.lineNumber) and \
00249            self.shouldSubroutinizeFunction(theExpression,parentStmt):
00250             DebugManager.debug('it is a function call to be subroutinized')
00251             return self.__canonicalizeFuncCall(theExpression,parentStmt)
00252         # if argument is a variable reference then don't hoist
00253         if (not forceIt and
00254             (isinstance(theExpression,str) and fe.is_id(theExpression)) 
00255             or 
00256             (isinstance(theExpression,fe.App) and isArrayReference(theExpression,self.__myUnit.symtab,parentStmt.lineNumber))
00257             or
00258             isinstance(theExpression,fe.Sel)):
00259             return theExpression
00260 
00261         # Anything else: create an assignment to a temporary and return that temporary
00262         (theNewTemp,newTempType,newTempTypeMods) = self.__newTemp(theExpression,parentStmt)
00263         self.__myNewExecs.append(self.__canonicalizeAssignStmt(fs.AssignStmt(theNewTemp,
00264                                                                              theExpression,
00265                                                                              lineNumber=parentStmt.lineNumber,
00266                                                                              label=False,
00267                                                                              lead=parentStmt.lead)))
00268         if (paramName):
00269             return fe.NamedParam(paramName,theNewTemp)
00270         else: 
00271             return theNewTemp
00272 
00273     def __canonicalizeExpression(self,theExpression,parentStmt):
00274         '''Canonicalize an expression tree by recursively replacing function calls with subroutine calls
00275            returns an expression that replaces theExpression'''
00276         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing expression "'+str(theExpression)+'"',newLine=False)
00277         self.__recursionDepth += 1
00278         replacementExpression = theExpression
00279         # variable or constant -> do nothing
00280         if isinstance(theExpression, str):
00281             DebugManager.debug(', which is a string (should be a constant or a variable => no canonicalization necessary)')
00282         # application expressions
00283         elif isinstance(theExpression,fe.App):
00284             if isinstance(theExpression.head,fe.App):
00285                 replacementExpression.head = self.__canonicalizeExpression(theExpression.head,parentStmt)
00286             # array reference -. do nothing
00287             elif isArrayReference(theExpression,self.__myUnit.symtab,parentStmt.lineNumber):
00288                 DebugManager.debug(', which is an array reference (no canonicalization necessary)')
00289             # function calls to subroutinize -> subroutinize and recursively canonicalize args
00290             elif self.shouldSubroutinizeFunction(theExpression,parentStmt):
00291                 DebugManager.debug(', it\'s a function call (subroutinized)')
00292                 replacementExpression = self.__canonicalizeFuncCall(theExpression,parentStmt)
00293             # function calls that won't be subroutinized -> recursively canonicalize args
00294             else: 
00295                 DebugManager.debug(', it\'s a function call (non-subroutinized)')
00296                 replacementArgs = []
00297                 for arg in theExpression.args:
00298                     replacementArgs.append(self.__canonicalizeExpression(arg,parentStmt))
00299                 replacementHead = theExpression.head
00300                 if not isinstance(theExpression.head,fe.Sel):
00301                     aSymtabEntry=self.__myUnit.symtab.lookup_name(theExpression.head)
00302                     # see if it is  a statement function and expand it
00303                     if (aSymtabEntry and isinstance(aSymtabEntry.entryKind,SymtabEntry.StatementFunctionEntryKind)):
00304                         parentStmt.beenModified = True
00305                         replacementExpression=self.__expandStmtFunExp(fe.App(replacementHead,replacementArgs))
00306                     # check whether we need to convert the function to the generic name (e.g. alog => log)
00307                     else:
00308                         if (is_intrinsic(theExpression.head) and theExpression.head.lower() != getGenericName(theExpression.head)) :
00309                             parentStmt.beenModified = True
00310                             replacementHead = getGenericName(theExpression.head)
00311                         replacementExpression = fe.App(replacementHead,replacementArgs)
00312         # Unary operation -> recursively canonicalize the sole subexpression
00313         elif isinstance(theExpression,fe.Unary):
00314             DebugManager.debug(', which is a unary op. with exp: "'+str(theExpression.exp)+'"')
00315             replacementExpression = theExpression.__class__(self.__canonicalizeExpression(theExpression.exp,parentStmt))
00316         # Binary operation -> recursively canonicalize both subexpressions
00317         elif isinstance(theExpression,fe.Ops):
00318             DebugManager.debug(', which is a binary op. with a1="'+str(theExpression.a1)+'", a2="'+str(theExpression.a2)+'"')
00319             a1Result = self.__canonicalizeExpression(theExpression.a1,parentStmt)
00320             a2result = self.__canonicalizeExpression(theExpression.a2,parentStmt)
00321             replacementExpression = fe.Ops(theExpression.op,a1Result,a2result)
00322         # Everything else...
00323         else:
00324             DebugManager.debug(', which is of type '+str(theExpression.__class__)+' that is assumed to require no canonicalization')
00325         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00326         self.__recursionDepth -= 1
00327         return replacementExpression
00328 
00329     def __canonicalizeSubCallStmt(self,aSubCallStmt):
00330         '''
00331         Canonicalize a subroutine call by hoisting all arguments
00332         (except simple variables) to temporaries.
00333         '''
00334         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing subroutine call statement "'+str(aSubCallStmt)+'"')
00335         self.__recursionDepth += 1
00336         # canonicalize each of the the expressions that serve as arguments
00337         replacementArgs = []
00338         # certain non-standard intrinsics (e.g. free) are subroutines rather than functions
00339         if (not isUsedNonStandard(aSubCallStmt.head)):
00340             for anArg in aSubCallStmt.args:
00341                 paramName=None
00342                 if isinstance(anArg,fe.NamedParam):
00343                     paramName=anArg.myId
00344                     anArg=anArg.myRHS
00345                 DebugManager.debug((self.__recursionDepth - 1)*'|\t'+'|- argument "'+str(anArg)+'" ',newLine=False)
00346                 argType=None
00347                 argTypeMod=None
00348                 try: 
00349                     argType = expressionType(anArg,self.__myUnit.symtab,aSubCallStmt.lineNumber)
00350                 except InferenceError, e :
00351                     DebugManager.warning("cannot canonicalize argument >"+str(anArg)+"< parsed as "+repr(anArg)+" because: "+e.msg,aSubCallStmt.lineNumber)
00352                     replacementArgs.append(anArg)
00353                     continue
00354                 # constant character expressions
00355                 if argType is not None and (isinstance(argType.entryKind,TypetabEntry.CharacterEntryKind) or \
00356                         (isinstance(argType.entryKind,TypetabEntry.BuiltInEntryKind) and argType.entryKind.type_name=='character')):
00357                     if not self._hoistStringsFlag:
00358                         DebugManager.debug('is a string expression (which we aren\'t hoisting)')
00359                         replacementArgs.append(anArg)
00360                     elif isinstance(anArg,str) and self.__myUnit.symtab.lookup_name(anArg):
00361                         DebugManager.debug('is a string variable (which we aren\'t hoisting)')
00362                         replacementArgs.append(anArg)
00363                     elif isinstance(anArg,fe.App) and isArrayReference(anArg,self.__myUnit.symtab,aSubCallStmt.lineNumber):
00364                         DebugManager.debug('is a character array reference (which we aren\'t hoisting)')
00365                         replacementArgs.append(anArg)
00366                     else:
00367                         DebugManager.debug('is a string expression to be hoisted:',newLine=False)
00368                         replacementArgs.append(self.__hoistExpression(anArg,aSubCallStmt,paramName))
00369                 # other constant expressions
00370                 elif fe.isConstantExpression(anArg):
00371                     if not self._hoistConstantsFlag:
00372                         DebugManager.debug('is a constant expression (which we aren\'t hoisting)')
00373                         replacementArgs.append(anArg)
00374                     else:
00375                         DebugManager.debug('is a constant expression to be hoisted:',newLine=False)
00376                         replacementArgs.append(self.__hoistExpression(anArg,aSubCallStmt,paramName))
00377                 # variables (with VariableEntry in symbol table) -> do nothing except for pointers to subroutinized functions and PARAMTERs 
00378                 elif isinstance(anArg,str):
00379                     symtabEntry=self.__myUnit.symtab.lookup_name(anArg)
00380                     if (symtabEntry
00381                         and
00382                         (globalTypeTable.lookupTypeId(symtabEntry.typetab_id).isExternal()
00383                          or 
00384                          isinstance(symtabEntry.entryKind,SymtabEntry.FunctionEntryKind))):
00385                         if (function2subroutine.wasSubroutinized(symtabEntry.getScopePrefix(self.__myUnit)+anArg)) :
00386                             replacementArgs.append(function2subroutine.name_init+anArg); 
00387                             aSubCallStmt.beenModified=True
00388                             DebugManager.debug('is an identifier referring to a subroutinized function')
00389                         else :
00390                             DebugManager.warning('argument '+anArg+' in call to '+aSubCallStmt.head+' is classified as a function but we have not seen the definition and will assume it is not going to be subroutinized' ,lineNumber=aSubCallStmt.lineNumber)
00391                             replacementArgs.append(anArg)
00392                     elif (symtabEntry and symtabEntry.constInit and self._hoistConstantsFlag):
00393                         DebugManager.debug('is a PARAMETER identifier to be hoisted:',newLine=False)
00394                         replacementArgs.append(self.__hoistExpression(anArg,aSubCallStmt,paramName,True))
00395                     else : 
00396                         DebugManager.debug('is an identifier')
00397                         replacementArgs.append(anArg)
00398                 # Array References -> do nothing
00399                 elif isinstance(anArg,fe.App) and isArrayReference(anArg,self.__myUnit.symtab,aSubCallStmt.lineNumber):
00400                     DebugManager.debug('is an array reference')
00401                     replacementArgs.append(anArg)
00402                 # everything else -> hoist and create an assignment to a temp variable
00403                 else:
00404                     DebugManager.debug('is a nontrivial expression to be hoisted:',newLine=False)
00405                     replacementArgs.append(self.__hoistExpression(anArg,aSubCallStmt,paramName))
00406         else :
00407             DebugManager.warning('arguments in call to a non-standard intrinsic subroutine '+str(aSubCallStmt.head)+' are not hoisted',lineNumber=aSubCallStmt.lineNumber)
00408             replacementArgs=aSubCallStmt.args
00409         # replace aCallStmt with the canonicalized version
00410         replacementStatement = fs.CallStmt(aSubCallStmt.head,
00411                                            replacementArgs,
00412                                            lineNumber=aSubCallStmt.lineNumber,
00413                                            label=aSubCallStmt.label,
00414                                            lead=aSubCallStmt.lead,
00415                                            internal=aSubCallStmt.internal)
00416         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00417         self.__recursionDepth -= 1
00418         return replacementStatement
00419 
00420     def __canonicalizeAssignStmt(self,anAssignStmt):
00421         '''Canonicalize an assigment statement by removing function calls from the rhs'''
00422         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing assignment statement "'+str(anAssignStmt)+'"')
00423         self.__recursionDepth += 1
00424         replacementStatement = fs.AssignStmt(anAssignStmt.get_lhs(),
00425                                              self.__canonicalizeExpression(anAssignStmt.get_rhs(),anAssignStmt),
00426                                              lineNumber=anAssignStmt.lineNumber,
00427                                              label=anAssignStmt.label,
00428                                              lead=anAssignStmt.lead)
00429         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00430         self.__recursionDepth -= 1
00431         return replacementStatement
00432 
00433     def __canonicalizeIfNonThenStmt(self,anIfNonThenStmt):
00434         '''Canonicalize if stmt (without "then") by converting to an if-then construct and then recursively
00435            canonicalizing the test component and the conditionally executed statement'''
00436         # the replacement statement should be the endif
00437         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing if statement (without "then") "'+str(anIfNonThenStmt)+'" => replacing with an if-then statement')
00438         handleDoTermination=False
00439         if (anIfNonThenStmt.label 
00440             and 
00441             self.__myUnit.symtab.labelRefs.has_key(str(anIfNonThenStmt.label)) 
00442             and 
00443             any(map(lambda l: isinstance(l,fs.DoStmt),self.__myUnit.symtab.labelRefs[str(anIfNonThenStmt.label)]))):
00444             # DO terminated by IfNonThenStmt
00445             # if there is only one reference we can save it by moving the label to a new  END DO that follows  the replacement of anIfNonThenStmt : 
00446             if (len(self.__myUnit.symtab.labelRefs[str(anIfNonThenStmt.label)])==1) :
00447                 handleDoTermination=True
00448             else : 
00449                 e=CanonError('IF statement "'+str(anIfNonThenStmt)+'" terminates DO construct "'\
00450                              +str((filter(lambda l: isinstance(l,fs.DoStmt),self.__myUnit.symtab.labelRefs[str(anIfNonThenStmt.label)]))[0])\
00451                              +'" and cannot be converted to an IF construct because references to its label other than from the above DO construct exist; list of all references: ['\
00452                              +' ; '.join('line '+str(l.lineNumber)+": "+str(l) for l in self.__myUnit.symtab.labelRefs[str(anIfNonThenStmt.label)])\
00453                              +"]",
00454                              anIfNonThenStmt.lineNumber)   
00455                 if CanonError._keepGoing:
00456                     DebugManager.warning(e.msg,e.lineNumber,DebugManager.WarnType.ifStmtToIfConstr)
00457                 else:
00458                     raise e
00459         self.__recursionDepth += 1
00460         # first append the new IfThenStmt
00461         newLabel=(not handleDoTermination) and anIfNonThenStmt.label or None # if we handle the do termination the label moves to a new END DO 
00462         self.__myNewExecs.append(fs.IfThenStmt(self.__canonicalizeExpression(anIfNonThenStmt.test,anIfNonThenStmt),
00463                                  ifFormatStr=anIfNonThenStmt.ifFormatStr,
00464                                  thenFormatStr='then',
00465                                  lineNumber=anIfNonThenStmt.lineNumber,
00466                                  label=newLabel,
00467                                  lead=anIfNonThenStmt.lead))
00468         self.__recursionDepth -= 1
00469         # append the canonicalized version of the executable statement
00470         anIfNonThenStmt.stmt.lead = anIfNonThenStmt.lead+'  '
00471         self.__canonicalizeExecStmt(anIfNonThenStmt.stmt)
00472         self.__recursionDepth += 1
00473         # insert the endif statement as the replacement
00474         newEndIf=fs.EndifStmt(lead=anIfNonThenStmt.lead)
00475         replacementStatement=None
00476         if handleDoTermination:
00477             self.__myNewExecs.append(newEndIf)
00478             # new END DO with label that was on anIfNonThenStmt
00479             replacementStatement=fs.EnddoStmt(None,label=anIfNonThenStmt.label,lead=anIfNonThenStmt.lead)
00480         else:
00481             replacementStatement = newEndIf
00482         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00483         self.__recursionDepth -= 1
00484         return replacementStatement
00485 
00486     def __canonicalizeIfThenStmt(self,anIfThenStmt):
00487         '''Canonicalize if-then stmt by canonicalizing the test component
00488         returns a list of statements that replace anIfThenStmt'''
00489         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing if-then statement "'+str(anIfThenStmt)+'"')
00490         self.__recursionDepth += 1
00491         replacementStatement = fs.IfThenStmt(self.__canonicalizeExpression(anIfThenStmt.test,anIfThenStmt),
00492                                              lineNumber=anIfThenStmt.lineNumber,
00493                                              label=anIfThenStmt.label,
00494                                              lead=anIfThenStmt.lead)
00495         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00496         self.__recursionDepth -= 1
00497         return replacementStatement
00498 
00499     def __canonicalizeElseifStmt(self,anElseifStmt):
00500         '''Canonicalize anElseifStmt by canonicalizing the test component.  Returns a canonicalized ElseifStmt that replaces anElseifStmt'''
00501         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing elseif-then statement "'+str(anElseifStmt)+'"')
00502         self.__recursionDepth += 1
00503         newExecsLength = len(self.__myNewExecs)
00504         replacementStatement = fs.ElseifStmt(self.__canonicalizeExpression(anElseifStmt.test,anElseifStmt),
00505                                              lineNumber=anElseifStmt.lineNumber,
00506                                              label=anElseifStmt.label,
00507                                              lead=anElseifStmt.lead)
00508         if len(self.__myNewExecs) > newExecsLength: # this is the case iff some new statements were inserted
00509             e=CanonError('elseif test-component "'+str(anElseifStmt.test)+'" requires hoisting, but the placement of the extra assignment(s) is problematic.',anElseifStmt.lineNumber)
00510             if CanonError._keepGoing:
00511                 DebugManager.warning(e.msg,e.lineNumber,DebugManager.WarnType.hoisting)
00512             else:
00513                 raise e
00514         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00515         self.__recursionDepth -= 1
00516         return replacementStatement
00517 
00518     def __canonicalizeDoStmt(self,aDoStmt):
00519         '''
00520         Canonicalize aDoStmt statement by canonicalizing the loop start, end, and stride expressions.  Returns a canonicalized DoStmt that replaces aDoStmt.
00521         '''
00522         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing do statement "'+str(aDoStmt)+'"')
00523         self.__recursionDepth += 1
00524         replacementStatement = aDoStmt
00525         if aDoStmt.loopControl:
00526             replacementStart = self.__canonicalizeExpression(aDoStmt.loopControl.start,aDoStmt)
00527             newExecsLength = len(self.__myNewExecs)
00528             replacementStatement = fs.DoStmt(aDoStmt.doName,
00529                                              aDoStmt.doLabel,
00530                                              fe.LoopControl(aDoStmt.loopControl.var,
00531                                                             replacementStart,
00532                                                             self.__canonicalizeExpression(aDoStmt.loopControl.end,aDoStmt),
00533                                                             self.__canonicalizeExpression(aDoStmt.loopControl.stride,aDoStmt)),
00534                                              lineNumber=aDoStmt.lineNumber,
00535                                              label=aDoStmt.label,
00536                                              lead=aDoStmt.lead)
00537             if len(self.__myNewExecs) > newExecsLength: # this is the case iff loopControl.end or loopControl.stride required hoisting
00538                 raise CanonError('Either loopControl.end "'+str(aDoStmt.loopControl.end)+'" or loopControl.stride "'+str(aDoStmt.loopControl.stride)+'" for DoStmt "'+str(aDoStmt)+'" requires hoisting, but the placement of the extra assignment(s) is problematic.',aDoStmt.lineNumber)
00539         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00540         self.__recursionDepth -= 1
00541         return replacementStatement
00542 
00543     def __canonicalizeWhileStmt(self,aWhileStmt):
00544         '''
00545         Canonicalize aWhileStmt statement by canonicalizing the test expression.  Returns a canonicalized while statement that replaces aWhileStmt.
00546         '''
00547         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing while statement "'+str(aWhileStmt)+'"')
00548         self.__recursionDepth += 1
00549         newExecsLength = len(self.__myNewExecs)
00550         replacementStatement = fs.WhileStmt(self.__canonicalizeExpression(aWhileStmt.testExpression,aWhileStmt),
00551                                             lineNumber=aWhileStmt.lineNumber,
00552                                             label=aWhileStmt.label,
00553                                             lead=aWhileStmt.lead)
00554         if len(self.__myNewExecs) > newExecsLength: # this is the case iff some new statements were inserted
00555             raise CanonError('while statement test expression "'+str(aWhileStmt.testExpression)+'" requires hoisting, but the placement of the extra assignment(s) is problematic.',aWhileStmt.lineNumber)
00556         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00557         self.__recursionDepth -= 1
00558         return replacementStatement
00559 
00560     def __canonicalizeSelectCaseStmt(self,aSelectCaseStmt):
00561         '''
00562         Canonicalize aSelectCaseStmt by canonicalizing the case expression.  Returns a canonicalized select case statement that replaces aSelectCaseStmt.
00563         '''
00564         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing select case statement "'+str(aSelectCaseStmt)+'"')
00565         self.__recursionDepth += 1
00566         replacementStatement = fs.SelectCaseStmt(self.__canonicalizeExpression(aSelectCaseStmt.caseExpression,aSelectCaseStmt),
00567                                                  lineNumber=aSelectCaseStmt.lineNumber,
00568                                                  label=aSelectCaseStmt.label,
00569                                                  lead=aSelectCaseStmt.lead)
00570         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00571         self.__recursionDepth -= 1
00572         return replacementStatement
00573 
00574     def __canonicalizeIOExpression(self,exp,parentStmt,paramName=None):
00575         '''
00576         Canonicalize an expression from an IO statement by hoisting any function calls
00577         '''
00578         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing an IO statement"'+str(parentStmt)+'"')
00579         self.__recursionDepth += 1
00580         newExp = exp
00581         if isinstance(exp,fe.App):
00582             appTypeId=appType(exp,self.__myUnit.symtab,parentStmt.lineNumber)
00583             if ((not isArrayReference(exp,self.__myUnit.symtab,parentStmt.lineNumber))
00584                 and
00585                 (not appTypeId in UnitCanonicalizer._ourPassiveTypeIds)):
00586                 newExp = self.__hoistExpression(exp,parentStmt,paramName)
00587         elif isinstance(exp,fe.Ops):
00588             newExp = fe.Ops(exp.op,
00589                             self.__canonicalizeIOExpression(exp.a1,parentStmt),
00590                             self.__canonicalizeIOExpression(exp.a2,parentStmt))
00591         elif isinstance(exp,fe.ParenExp):
00592             newExp = fe.ParenExp(self.__canonicalizeIOExpression(exp.exp,parentStmt))
00593         elif isinstance(exp,fe.Umi):
00594             newExp = fe.Umi(self.__canonicalizeIOExpression(exp.exp,parentStmt))
00595         elif isinstance(exp,fe.Upl):
00596             newExp = fe.Upl(self.__canonicalizeIOExpression(exp.exp,parentStmt))
00597         elif isinstance(exp,fe.Not):
00598             newExp = fe.Not(self.__canonicalizeIOExpression(exp.exp,parentStmt))
00599         elif isinstance(exp,fe.MultiParenExp):
00600             newList = []
00601             for item in exp.expList:
00602                 newList.append(self.__canonicalizeIOExpression(item,parentStmt))
00603             newExp = fe.MultiParenExp(newList)
00604         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00605         self.__recursionDepth -= 1
00606         return newExp
00607 
00608     def __canonicalizeIOStmt(self,anIOStmt):
00609         '''
00610         Canonicalize an IOStmt by canonicalizing the ioCtrlSpecList and the itemList. Returns a canonicalized IO statement that replaces anIOStmt.
00611         '''
00612         DebugManager.debug(self.__recursionDepth*'|\t'+'canonicalizing an IO statement"'+str(anIOStmt)+'"')
00613         self.__recursionDepth += 1
00614         replacementStmt = anIOStmt
00615         for item in replacementStmt.itemList:
00616             newExp = self.__canonicalizeIOExpression(item,replacementStmt)
00617             if newExp != item:
00618                 index = replacementStmt.itemList.index(item)
00619                 replacementStmt.itemList.insert(index,newExp)
00620                 replacementStmt.itemList.remove(item)
00621                 replacementStmt.modified = True
00622         DebugManager.debug((self.__recursionDepth-1)*'|\t'+'|_')
00623         self.__recursionDepth -= 1
00624         return replacementStmt
00625 
00626     def __expandStmtFunExp(self,anExp):
00627         newSon = anExp
00628         if isinstance(anExp,fe.App):
00629             for stmtFnStmt in self.__stmtFunctionStmts:
00630                 newArgs = []
00631                 for anArg in anExp.args:
00632                     newArgs.append(self.__expandStmtFunExp(anArg))
00633                 if anExp.head == stmtFnStmt.name:
00634                     newSon = fe.ParenExp(stmtFnStmt.body)
00635                     # replace args
00636                     newSon = replaceArgs(str(newSon),stmtFnStmt.args,newArgs)
00637                 else:
00638                     newSon = fe.App(anExp.head,newArgs)
00639         elif isinstance(anExp,fe.Ops):
00640             newSon = fe.Ops(anExp.op,
00641                             self.__expandStmtFunExp(anExp.a1),
00642                             self.__expandStmtFunExp(anExp.a2))
00643         elif isinstance(anExp,fe.ParenExp):
00644             newSon = fe.ParenExp(self.__expandStmtFunExp(anExp.exp))
00645         elif isinstance(anExp,fe.Umi):
00646             newSon = fe.Umi(self.__expandStmtFunExp(anExp.exp))
00647         elif isinstance(anExp,fe.Upl):
00648             newSon = fe.Upl(self.__expandStmtFunExp(anExp.exp))
00649         elif isinstance(anExp,fe.Not):
00650             newSon = fe.Not(self.__expandStmtFunExp(anExp.exp))
00651         elif isinstance(anExp,fe.MultiParenExp):
00652             newList = []
00653             for item in anExp.expList:
00654                 newList.append(self.__expandStmtFunExp(item))
00655                 newSon = fe.MultiParenExp(newList)
00656         return newSon
00657         
00658 
00659     def __expandStmtFunction(self,anExecStmt):
00660         if hasattr(anExecStmt,'_sons'):
00661             for aSon in anExecStmt.get_sons():
00662                 theSon = getattr(anExecStmt,aSon)
00663                 newSon = self.__expandStmtFunExp(theSon)
00664                 anExecStmt.set_son(aSon,newSon)
00665         return anExecStmt
00666 
00667     def __canonicalizeExecStmt(self,anExecStmt):
00668         # We were previously working with the assumption that an original statement is modified as part of the canonicalization process
00669         # if and only if at least one new statement has been added.
00670         # This is not true, as for example we canonicalize y = alog(x) to y = log(x)
00671         # hence, we have added a flag "beenModified" which indicates that an expression should be replaced by the canonicalized version
00672         anExecStmt.beenModified = False
00673         newExecsLength = len(self.__myNewExecs) # store the current number of execs (to determine afterwards whether we've added some)
00674         replacementStatement = anExecStmt
00675         replacementStatement = self.__expandStmtFunction(replacementStatement)
00676         if isinstance(anExecStmt,fs.CallStmt):
00677             replacementStatement = self.__canonicalizeSubCallStmt(anExecStmt)
00678         elif isinstance(anExecStmt,fs.AssignStmt):
00679             replacementStatement = self.__canonicalizeAssignStmt(anExecStmt)
00680         elif isinstance(anExecStmt,fs.IfNonThenStmt):
00681             replacementStatement = self.__canonicalizeIfNonThenStmt(anExecStmt)
00682         elif isinstance(anExecStmt,fs.IfThenStmt):
00683             replacementStatement = self.__canonicalizeIfThenStmt(anExecStmt)
00684         elif isinstance(anExecStmt,fs.ElseifStmt):
00685             replacementStatement = self.__canonicalizeElseifStmt(anExecStmt)
00686         elif isinstance(anExecStmt,fs.DoStmt):
00687             replacementStatement = self.__canonicalizeDoStmt(anExecStmt)
00688         elif isinstance(anExecStmt,fs.WhileStmt):
00689             replacementStatement = self.__canonicalizeWhileStmt(anExecStmt)
00690         elif isinstance(anExecStmt,fs.SelectCaseStmt):
00691             replacementStatement = self.__canonicalizeSelectCaseStmt(anExecStmt)
00692         elif isinstance(anExecStmt,fs.IOStmt):
00693             replacementStatement = self.__canonicalizeIOStmt(anExecStmt)
00694         else:
00695             DebugManager.debug('Statement "'+str(anExecStmt)+'" is assumed to require no canonicalization')
00696         if self.__recursionDepth != 0:
00697             raise CanonError('Recursion depth did not resolve to zero when canonicalizing '+str(anExecStmt),anExecStmt.lineNumber)
00698         # determine whether a change was made
00699         if anExecStmt.beenModified or \
00700            len(self.__myNewExecs) > newExecsLength: # some new statements were inserted
00701             self.__myNewExecs.append(replacementStatement) # => replace anExecStmt with the canonicalized version
00702         else: # no new statements were inserted
00703             self.__myNewExecs.append(anExecStmt) # => leave anExecStmt alone
00704 
00705     def __canonicalizeFunctionDecls(self,aDecl,subroutineBlock):
00706         if isinstance(aDecl,fs.StmtFnStmt):
00707             self.__stmtFunctionStmts.append(aDecl)
00708         if self._keepFunctionDecl:
00709             self.__myNewDecls.append(aDecl)
00710         if isinstance(aDecl,fs.FunctionStmt):
00711             self.setFunctionBlockFlag(True)
00712             (self.__outParam,subroutineStmt) = function2subroutine.\
00713                                                convertFunctionOrEntryStmt(aDecl,self.__myUnit)
00714             subroutineBlock.append(subroutineStmt)
00715             self.__resultDecl = function2subroutine.\
00716                          createResultDecl(aDecl,self.__outParam)
00717             self.setCreateResultDeclFlag(True)
00718         elif not self._functionBlockFlag:
00719             if not self._keepFunctionDecl:
00720                 self.__myNewDecls.append(aDecl)
00721         elif isinstance(aDecl,fs.EndStmt):
00722             newEndStmt = fs.EndSubroutineStmt(lineNumber=aDecl.lineNumber,label=aDecl.label,lead=aDecl.lead)
00723             subroutineBlock.append(newEndStmt)
00724             self.__myNewDecls.extend(subroutineBlock)
00725             self.setFunctionBlockFlag(False)
00726         elif isinstance(aDecl,fs.Comments):
00727             if aDecl.rawline.strip() == '':
00728                 pass
00729             else:
00730                 subroutineBlock.append(aDecl)
00731         elif self._createResultDeclFlag \
00732                  and not isinstance(aDecl,fs.UseStmt):
00733             if self.__resultDecl is not None:
00734                 subroutineBlock.append(self.__resultDecl)
00735                 self.setCreateResultDeclFlag(False)
00736             elif isinstance(aDecl,fs.TypeDecl):
00737                 (aDecl,resultDecl,resultDeclFlag) = function2subroutine.updateTypeDecl(\
00738                     aDecl,self.__outParam,self.__myNewDecls)
00739                 self.setCreateResultDeclFlag(not resultDeclFlag)
00740                 if resultDeclFlag:
00741                     subroutineBlock.append(resultDecl)
00742             if aDecl is not None:
00743                 subroutineBlock.append(aDecl)
00744         else:
00745             subroutineBlock.append(aDecl)
00746 
00747     def __createFuncSubPairs(self):
00748         oldFuncnewSubPairs = []
00749         for aSubUnit in self.__myUnit.ulist:
00750             if isinstance(aSubUnit.uinfo,fs.SubroutineStmt) and \
00751                    aSubUnit.uinfo.name.startswith(function2subroutine.name_init):
00752                 if aSubUnit.uinfo.name[0:6] != function2subroutine.name_init :
00753                     raise CanonError('Tried to strip "'+aSubUnit.uinfo.name[0:6]+'"' \
00754                                     +' from the beginning of "'+aSubUnit.uinfo.name+'"',aSubUnit.uinfo.lineNumber)
00755                 DebugManager.debug('searching declarations to convert old function name "'+aSubUnit.uinfo.name[6:]+'"' \
00756                                   +' to new subroutine name "'+aSubUnit.uinfo.name+'"')
00757                 oldFuncnewSubPairs.append([aSubUnit.uinfo.name[6:],
00758                                            aSubUnit.uinfo.name])
00759         return oldFuncnewSubPairs
00760         
00761     def __processInterfaceBlocks(self,oldFuncnewSubPairs):
00762         interfaceBlockFlag = False
00763         interfaceBlock = []
00764         self.__myNewDecls = []
00765         for aDecl in self.__myUnit.decls:
00766             # accumulate an interface block and process it
00767             if interfaceBlockFlag:
00768                 interfaceBlock.append(aDecl)
00769                 if isinstance(aDecl,fs.EndInterfaceStmt):
00770                     newInterfaceBlock = function2subroutine.\
00771                                         convertInterfaceBlock(interfaceBlock,oldFuncnewSubPairs,self._keepFunctionDecl)
00772                     self.__myNewDecls.extend(newInterfaceBlock)
00773                     interfaceBlockFlag = False
00774                     interfaceBlock = []
00775             elif isinstance(aDecl,fs.InterfaceStmt):
00776                 interfaceBlockFlag = True
00777                 interfaceBlock.append(aDecl)
00778             # if not part of the interface block, convert decls and add them
00779             else:
00780                 (newDecl,modified) = function2subroutine.\
00781                                      convertFunctionDecl(aDecl,oldFuncnewSubPairs)
00782                 if (not modified):
00783                     self.__myNewDecls.append(aDecl)
00784                 else:
00785                     if (self._keepFunctionDecl):
00786                         self.__myNewDecls.append(aDecl)
00787                     self.__myNewDecls.append(newDecl)
00788 
00789     def __createNewSubroutine(self,aUnit,subroutineDecls):
00790         if isinstance(aUnit.uinfo,fs.FunctionStmt):
00791             DebugManager.debug(5*'-'+'>'+'called __createNewSubroutine ' \
00792                                + 'on unit "'+str(aUnit)+'",' \
00793                                + 'with subroutineDecls='+str(subroutineDecls)+',' \
00794                                +' with symtab "'+aUnit.symtab.debug()+'"')
00795             self.__processedFunctions.append(aUnit.uinfo.name)
00796             if self._keepFunctionDecl:
00797                 newUnit = function2subroutine.\
00798                           convertFunction(aUnit,self.__myNewExecs,subroutineDecls)
00799                 # if the unit has no parent, then it was the original unit.
00800                 if aUnit.parent is None:
00801                     # create a parent
00802                     aUnit.parent = fortUnit.Unit()
00803                     # append new unit & original unit (already processed)
00804                     aUnit.parent.ulist.append(aUnit)
00805                     aUnit.parent.ulist.append(newUnit)
00806                     # return parent
00807                     aUnit = self.__myUnit.parent
00808                 else:
00809                     aUnit.parent.ulist.append(newUnit)                    
00810             else:
00811                 aUnit = function2subroutine.convertFunction(aUnit,self.__myNewExecs,subroutineDecls)
00812         return aUnit
00813 
00814     def __canonicalizeExecStmts(self,execList):
00815         DebugManager.debug('canonicalizing executable statements:')
00816         for anExecStmt in execList:
00817             DebugManager.debug('[Line '+str(anExecStmt.lineNumber)+']:')
00818             try:
00819                 self.__canonicalizeExecStmt(anExecStmt)
00820             except InferenceError,e:
00821                 raise CanonError('Caught InferenceError: '+e.msg,anExecStmt.lineNumber)
00822             except SymtabError,e: # add a lineNumber to SymtabErrors that don't have one
00823                 e.lineNumber = e.lineNumber or anExecStmt.lineNumber
00824                 raise e
00825             
00826     def __canonicalizeUseAndExternalStmts(self,aDecl):
00827         if (isinstance(aDecl,fs.UseStmt)):
00828             if isinstance(aDecl, fs.UseAllStmt):
00829                 newRenameList=[]
00830                 if aDecl.renameList:
00831                     for renameItem in aDecl.renameList:
00832                         scopedName=aDecl.moduleName+":"+renameItem.rhs
00833                         if function2subroutine.wasSubroutinized(scopedName): 
00834                             newRenameList.append(fs._PointerInit(function2subroutine.name_init+renameItem.lhs,
00835                                                                  function2subroutine.name_init+renameItem.rhs))
00836                             if (self._keepFunctionDecl):
00837                                 newRenameList.append(renameItem)
00838                             aDecl.modified=True
00839                         else: 
00840                             newRenameList.append(renameItem)
00841                 if (aDecl.modified):
00842                     aDecl.renameList=newRenameList
00843             elif isinstance(aDecl, fs.UseOnlyStmt):
00844                 newOnlyList=[]
00845                 for onlyItem in aDecl.onlyList:
00846                     if isinstance(onlyItem,fs._PointerInit):
00847                         if function2subroutine.wasSubroutinized(aDecl.moduleName+":"+onlyItem.rhs):
00848                             newOnlyList.append(fs._PointerInit(function2subroutine.name_init+onlyItem.lhs,
00849                                                                function2subroutine.name_init+onlyItem.rhs))
00850                             if (self._keepFunctionDecl):
00851                                 newOnlyList.append(onlyItem)
00852                             aDecl.modified=True
00853                         else:
00854                             newOnlyList.append(onlyItem)
00855                     elif function2subroutine.wasSubroutinized(aDecl.moduleName+":"+onlyItem):
00856                         newOnlyList.append(function2subroutine.name_init+onlyItem)
00857                         if (self._keepFunctionDecl):
00858                             newOnlyList.append(onlyItem)
00859                         aDecl.modified=True
00860                     else: 
00861                         newOnlyList.append(onlyItem)
00862                 if (aDecl.modified): 
00863                     aDecl.onlyList=newOnlyList
00864         elif (isinstance(aDecl,fs.ExternalStmt)):
00865             newProcedureNames=[]
00866             for p in aDecl.procedureNames:
00867                 if (function2subroutine.wasSubroutinized(p)):
00868                     newProcedureNames.append(function2subroutine.name_init+p)
00869                     aDecl.modified=True
00870                 else:
00871                     newProcedureNames.append(p)
00872             if (aDecl.modified):
00873                 aDecl.procedureNames=newProcedureNames
00874                     
00875 
00876     def canonicalizeUnit(self):
00877         '''Recursively canonicalize \p aUnit'''
00878         DebugManager.debug(('+'*55)+' Begin canonicalize unit <'+str(self.__myUnit.uinfo)+'> '+(55*'+'))
00879         DebugManager.debug('local '+self.__myUnit.symtab.debug())
00880         DebugManager.debug('subunits (len ='+str(len(self.__myUnit.ulist))+'):')
00881         if (not self.__myUnit.parent and self.__myUnit.uinfo): # would have been added in the parent
00882             lead=self.__myUnit.uinfo.lead or ''
00883             addIt=False
00884             if self.__myUnit.ulist:
00885                 addIt=True # if we have subunits add it regardless
00886             # try to get a lead and see if we have non-comment execs 
00887             ncExecsIter=itertools.ifilter(lambda l: not isinstance(l, fs.Comments),self.__myUnit.execs)
00888             try : 
00889                 lead=ncExecsIter.next().lead
00890                 addIt=True # made it here, i.e. we have execs and need to add it
00891                 # see if we can get a better lead from non-comment decls 
00892                 ncDeclsIter=itertools.ifilter(lambda l: not isinstance(l, fs.Comments),self.__myUnit.decls)
00893                 try : 
00894                     lead=ncDeclsIter.next().lead
00895                 except StopIteration, e:
00896                     pass # doesn't matter 
00897             except StopIteration, e: # no exec statements, no reason to add it here. 
00898                 pass # still we may have to add it because of subunits
00899             if (addIt and not UnitCanonicalizer._overloadingMode):
00900                 self.__myUnit.decls.insert(0, #always insert as the first decl to avoid ordering problems
00901                                            fs.UseAllStmt(moduleName=subroutinizedIntrinsics.getModuleName(),
00902                                                          renameList=None,
00903                                                          lead=lead))
00904         newList = []
00905         for subUnit in self.__myUnit.ulist:
00906             DebugManager.debug(5*'%'+'>'+'canon.canonicalizeUnit: ' \
00907                               +'canonicalizing subunit '+str(subUnit))
00908             # if the unit is new, as a result of function transformation,
00909             # skip processing
00910             if isinstance(subUnit.uinfo,fs.SubroutineStmt) and \
00911                      subUnit.uinfo.name.startswith(function2subroutine.name_init):
00912                 DebugManager.debug(5*'%'+'>'+'\t skipping this subunit because we generated it')
00913                 newList.append(subUnit)
00914             elif subUnit.uinfo.name in self.__processedFunctions:
00915                 DebugManager.debug(5*'%'+'>'+'\t skipping this subunit because we already processed it')
00916                 newList.append(subUnit)
00917             else:
00918                 newUnit = UnitCanonicalizer(subUnit).canonicalizeUnit()
00919                 newList.append(newUnit)
00920         self.__myUnit.ulist = newList
00921         
00922         subroutineBlock = []    
00923         for aDecl in self.__myUnit.decls:
00924             self.__canonicalizeUseAndExternalStmts(aDecl)
00925             self.__canonicalizeFunctionDecls(aDecl,subroutineBlock)
00926 
00927         ## replace the declaration statements for the unit
00928         if not isinstance(self.__myUnit.uinfo,fs.FunctionStmt):
00929             self.__myUnit.decls = self.__myNewDecls
00930             subroutineDecls = []
00931         else:
00932             subroutineDecls = self.__myNewDecls
00933 
00934         self.__myNewDecls = [] # empty it out, the following line may add new declarations
00935         self.__canonicalizeExecStmts(self.__myUnit.execs)
00936         # set the leading whitespace for the new declarations and add them to the unit
00937         for aDecl in self.__myNewDecls:
00938             aDecl.lead = self.__myUnit.uinfo.lead+'  '
00939         if not isinstance(self.__myUnit.uinfo,fs.FunctionStmt):
00940             self.__myUnit.decls.extend(self.__myNewDecls)
00941         subroutineDecls.extend(self.__myNewDecls)
00942 
00943         # replace the executable statements for the unit
00944         if not isinstance(self.__myUnit.uinfo,fs.FunctionStmt):
00945             self.__myUnit.execs = self.__myNewExecs
00946 
00947         # for function units, also create a corresponding subroutine
00948         self.__myUnit = self.__createNewSubroutine(self.__myUnit,subroutineDecls)
00949         
00950         # build list of old function/new subroutine name pairs 
00951         oldFuncnewSubPairs = self.__createFuncSubPairs()
00952         # accumulate an interface block and process it
00953         self.__processInterfaceBlocks(oldFuncnewSubPairs)
00954 
00955         self.__myUnit.decls = self.__myNewDecls
00956             
00957         DebugManager.debug(('+'*54)+' End canonicalize unit <'+str(self.__myUnit.uinfo)+'> '+(54*'+')+'\n\n')
00958 
00959         return self.__myUnit
00960 
00961 
 All Classes Namespaces Files Functions Variables