def _endInterface(anEndInterfaceStmt, cur):
    # get all the procedurenames from the mock symtab...
    mockSymtab = cur.val.symtab
    if (cur.val._in_iface.name):
        ifName = cur.val._in_iface.name
        cur.val.symtab = cur.val.symtab.parent
        genericSymtabEntry = cur.val.symtab.lookup_name(ifName)
        for name in mockSymtab.ids.keys():
            try:
                specificSymtabEntry = cur.val.symtab.lookup_name(name)
                if not specificSymtabEntry:
                    specifcSymtabEntry = SymtabEntry(
                        SymtabEntry.ProcedureEntryKind())
                    cur.val.symtab.enter_name(name, specifcSymtabEntry)
                    DebugManager.debug(
                        '\tmodule procedure NOT already present in symbol table -- adding '
                        + specifcSymtabEntry.debug(name))
                else:
                    DebugManager.debug(
                        '\tmodule procedure already has SymtabEntry' +
                        specificSymtabEntry.debug(name))
                    # if the entry has a type, we know it's a function
                    newEntryKind = specificSymtabEntry.typetab_id and SymtabEntry.FunctionEntryKind \
                                   or SymtabEntry.ProcedureEntryKind
                    specificSymtabEntry.enterEntryKind(newEntryKind())
                genericSymtabEntry.addResolveName(name, specifcSymtabEntry)
            except SymtabError, e:  # add lineNumber and symbol name to any SymtabError we encounter
                e.lineNumber = e.lineNumber or aProcedureStmt.lineNumber
                e.symbolName = e.symbolName or aProcedureName
                raise e
def _beginDrvdTypeDefn(aDrvdTypeDefn, curr):
    'derived type definition -- record type in symbol table and set the name on the unit'
    localSymtab = curr.val.symtab
    theSymtabEntry = localSymtab.lookup_name_local(aDrvdTypeDefn.name)
    access = None  # DrvdTypeDefn currently cannot parse qualifiers
    curr.val._in_drvdType = aDrvdTypeDefn.name
    if theSymtabEntry:  # already in symtab, shouldn't happen
        theSymtabEntry.enterEntryKind(
            SymtabEntry.DerivedTypeEntryKind(aDrvdTypeDefn.base_type))
    else:
        newSymtabEntry = SymtabEntry(SymtabEntry.DerivedTypeEntryKind(
            aDrvdTypeDefn.base_type),
                                     dimensions=None,
                                     length=None,
                                     origin='local',
                                     access=access)
        typetab_id = globalTypeTable.enterNamedType(curr.val._in_drvdType,
                                                    curr.val.symtab)
        newSymtabEntry.typetab_id = typetab_id
        DebugManager.debug('defn "' + str(aDrvdTypeDefn) +
                           '" NOT already present in symbol table => adding ' +
                           str(newSymtabEntry.debug(aDrvdTypeDefn.name)))
        localSymtab.enter_name(aDrvdTypeDefn.name, newSymtabEntry)
    # add to type table & set typetab_id
    return aDrvdTypeDefn
def _processExternalStmt(anExternalStmt, curr):
    localSymtab = curr.val.symtab
    DebugManager.debug('[Line ' + str(anExternalStmt.lineNumber) +
                       ']: stmt2unit._processExternalStmt: called on "' +
                       str(anExternalStmt) + '" with localSymtab ' +
                       str(localSymtab))
    for aProcedureName in anExternalStmt.procedureNames:
        try:
            theSymtabEntry = localSymtab.lookup_name(aProcedureName)
            if not theSymtabEntry:  # first guess - assume it is an external subroutine
                newSymtabEntry = SymtabEntry(
                    SymtabEntry.SubroutineEntryKind(),
                    typetab_id=globalTypeTable.getType(anExternalStmt,
                                                       localSymtab),
                    origin='external')
                localSymtab.enter_name(aProcedureName, newSymtabEntry)
                DebugManager.debug(
                    '\tprocedure NOT already present in symbol table -- adding '
                    + newSymtabEntry.debug(aProcedureName))
            else:
                DebugManager.debug('\tprocedure already has SymtabEntry' +
                                   theSymtabEntry.debug(aProcedureName))
                # if the entry has a type, we know it's a function
                newEntryKind = theSymtabEntry.typetab_id and SymtabEntry.FunctionEntryKind \
                                                    or SymtabEntry.SubroutineEntryKind
                theSymtabEntry.enterEntryKind(newEntryKind())
        except SymtabError, e:  # add lineNumber and symbol name to any SymtabError we encounter
            e.lineNumber = e.lineNumber or anExternalStmt.lineNumber
            e.symbolName = e.symbolName or aProcedureName
            raise e
def _processDimensionStmt(aDimensionStmt, curr):
    localSymtab = curr.val.symtab
    DebugManager.debug('[Line ' + str(aDimensionStmt.lineNumber) +
                       ']: stmt2unit._processDimensionStmt(' +
                       str(aDimensionStmt) + ') with symbol table ' +
                       str(localSymtab))
    for aDimensionSpec in aDimensionStmt.lst:
        try:
            theSymtabEntry = localSymtab.lookup_name_local(
                aDimensionSpec.arrayName)
            if theSymtabEntry:
                DebugManager.debug(
                    '\tvariable "' + aDimensionSpec.arrayName +
                    '" already present in local symbol table as ' +
                    theSymtabEntry.debug(aDimensionSpec.arrayName))
                theSymtabEntry.enterDimensions(tuple(aDimensionSpec.arraySpec))
            else:
                newSymtabEntry = SymtabEntry(SymtabEntry.VariableEntryKind(),
                                             dimensions=tuple(
                                                 aDimensionSpec.arraySpec),
                                             origin='local')
                DebugManager.debug(
                    '\tvariable "' + aDimensionSpec.arrayName +
                    '" NOT already present in symbol table -- adding ' +
                    newSymtabEntry.debug(aDimensionSpec.arrayName))
                localSymtab.enter_name(aDimensionSpec.arrayName,
                                       newSymtabEntry)
        except SymtabError, e:  # add lineNumber and symbol name to any SymtabError we encounter
            e.lineNumber = e.lineNumber or aDimensionStmt.lineNumber
            e.symbolName = e.symbolName or aDimensionSpec.arrayName
            raise e
def _processCommonStmt(aCommonStmt, curr):
    localSymtab = curr.val.symtab
    DebugManager.debug('[Line ' + str(aCommonStmt.lineNumber) + ']: ' +
                       sys._getframe().f_code.co_name + ' called on "' +
                       repr(aCommonStmt) + '" with localSymtab ' +
                       localSymtab.debug())
    commonTypeId = None
    updateDeclTypeList = []
    for aDecl in aCommonStmt.declList:
        try:
            aDeclName = ""
            if isinstance(aDecl, fe.App):
                aDeclName = aDecl.head
            else:
                aDeclName = aDecl
            theSymtabEntry = localSymtab.lookup_name(aDeclName)
            if not theSymtabEntry:
                # symtab entry will be added by declaration
                newSymtabEntry = SymtabEntry(
                    SymtabEntry.VariableEntryKind(),
                    origin=Symtab._ourCommonScopePrefix + aCommonStmt.name)
                localSymtab.enter_name(aDeclName, newSymtabEntry)
                if isinstance(aDecl, fe.App):
                    newSymtabEntry.enterDimensions(aDecl.args)
                if commonTypeId:
                    newSymtabEntry.typetab_id = commonTypeId
                else:
                    updateDeclTypeList.append(newSymtabEntry)
                DebugManager.debug(
                    '\tcommon variable NOT already present in symbol table -- adding '
                    + newSymtabEntry.debug(aDeclName))
            else:
                DebugManager.debug(
                    '\tcommon variable already has SymtabEntry' +
                    theSymtabEntry.debug(aDeclName))
                theSymtabEntry.enterEntryKind(SymtabEntry.VariableEntryKind())
                if isinstance(aDecl, fe.App):
                    theSymtabEntry.enterDimensions(aDecl.args)
                theSymtabEntry.updateOrigin(Symtab._ourCommonScopePrefix +
                                            aCommonStmt.name)
                commonTypeId = theSymtabEntry.typetab_id
        except SymtabError, e:  # add lineNumber and symbol name to any SymtabError we encounter
            e.lineNumber = e.lineNumber or aCommonStmt.lineNumber
            e.symbolName = e.symbolName or aDeclName
            raise e
def _processProcedureStmt(aProcedureStmt, curr):
    localSymtab = curr.val.symtab
    DebugManager.debug('[Line ' + str(aProcedureStmt.lineNumber) +
                       ']: stmt2unit._processProcedureStmt: called on "' +
                       str(aProcedureStmt) + '" with localSymtab ' +
                       str(localSymtab))
    for aProcedureName in aProcedureStmt.procedureList:
        try:
            theSymtabEntry = localSymtab.lookup_name(aProcedureName)
            if not theSymtabEntry:
                newSymtabEntry = SymtabEntry(SymtabEntry.ProcedureEntryKind())
                localSymtab.enter_name(aProcedureName, newSymtabEntry)
                DebugManager.debug(
                    '\t_processProcedureStmt: module procedure NOT already present in symbol table -- adding '
                    + newSymtabEntry.debug(aProcedureName))
            else:
                DebugManager.debug(
                    '\t_processProcedureStmt: module procedure already has SymtabEntry'
                    + theSymtabEntry.debug(aProcedureName))
                # if the entry has a type, we know it's a function
                newEntryKind = theSymtabEntry.typetab_id and SymtabEntry.FunctionEntryKind \
                                                    or SymtabEntry.ProcedureEntryKind
                theSymtabEntry.enterEntryKind(newEntryKind())
                theGenericSymtabEntry = localSymtab.lookup_name(
                    curr.val._in_iface.name)
                if (theGenericSymtabEntry.genericInfo):
                    if (theGenericSymtabEntry.genericInfo.genericName !=
                            curr.val._in_iface.name.lower()):
                        raise SymtabError('mismatched generic name')
                    if (not (aProcedureName in theGenericSymtabEntry.
                             genericInfo.resolvableTo.keys())):
                        theGenericSymtabEntry.genericInfo.resolvableTo[
                            aProcedureName] = theSymtabEntry
                else:
                    theGenericSymtabEntry.genericInfo = GenericInfo()
                    theGenericSymtabEntry.genericInfo.genericName = curr.val._in_iface.name.lower(
                    )
                    theGenericSymtabEntry.genericInfo.resolvableTo[
                        aProcedureName] = theSymtabEntry
        except SymtabError, e:  # add lineNumber and symbol name to any SymtabError we encounter
            e.lineNumber = e.lineNumber or aProcedureStmt.lineNumber
            e.symbolName = e.symbolName or aProcedureName
            raise e
def _processEntry(self, cur):
    '''
    add the entry name to 
       1. The local symtab for the object
       2. The unit symtab
       3. The parent of the unit (if there is one)
    '''
    currentSymtab = cur.val.symtab
    if (currentSymtab.parent and (self.name in currentSymtab.parent.ids)):
        # this must be the definition of a previously  declared module procedure
        mpSymTabEntry = currentSymtab.parent.ids[self.name]
        if (not isinstance(mpSymTabEntry.entryKind,
                           SymtabEntry.ProcedureEntryKind)
                or mpSymTabEntry.genericInfo is None):
            raise SymtabError('parent symbol is not a module procedure')
        entry = SymtabEntry(
            currentSymtab.lookup_name(cur.val.uinfo.name).entryKind)
        mpSymTabEntry.entryKind = entry.entryKind
        mpSymTabEntry.typetab_id = entry.typetab_id
        entry.genericInfo = mpSymTabEntry.genericInfo
        currentSymtab.enter_name(self.name, entry)
    else:
        entry = SymtabEntry(
            currentSymtab.lookup_name(cur.val.uinfo.name).entryKind)
        currentSymtab.enter_name(self.name, entry)
        DebugManager.debug('[Line ' + str(self.lineNumber) +
                           ']: new unit symtab entry ' +
                           entry.debug(self.name))
        if currentSymtab.parent:
            currentSymtab.replicateEntry(self.name,
                                         "local",
                                         self.name,
                                         currentSymtab.parent,
                                         replicatingUp=True)
            DebugManager.debug('[Line ' + str(self.lineNumber) +
                               ']: new PARENT unit symtab entry (see above)')
    DebugManager.debug('[Line ' + str(self.lineNumber) +
                       ']: stmt2unit._processEntry() for ' + str(self) +
                       ': with symtab ' + str(currentSymtab) +
                       ' with parent symtab ' + str(currentSymtab.parent))
    if (isinstance(self, fs.FunctionStmt)):
        cur.val._in_functionDecl = self
    return self
def _processTypedeclStmt(aTypeDeclStmt, curr):
    'type declaration -- record type in symbol table'
    localSymtab = curr.val.symtab
    newType = (aTypeDeclStmt.__class__, aTypeDeclStmt.mod)
    newLength = None
    DebugManager.debug('[Line ' + str(aTypeDeclStmt.lineNumber) + ']: ' +
                       sys._getframe().f_code.co_name + ' for ' +
                       repr(aTypeDeclStmt) + ' with default dimensions ' +
                       str(aTypeDeclStmt.dimension))
    access = None
    inDrvdTypeDefn = curr.val._in_drvdType
    for anAttribute in aTypeDeclStmt.attrs:
        if isinstance(
                anAttribute,
                str) and anAttribute.lower() in Symtab.ourSpecificAccessKWs:
            access = anAttribute.lower()
    for aDecl in aTypeDeclStmt.decls:
        DebugManager.debug('\tProcessing decl ' + repr(aDecl) + ' ... ',
                           newLine=False)
        (name, newDimensions) = typesep(aDecl, aTypeDeclStmt.dimension)
        if inDrvdTypeDefn:
            name = inDrvdTypeDefn + ":" + name
        try:
            # set the length for character statements
            if (aTypeDeclStmt.kw_str == 'character'):
                newLength = aTypeDeclStmt.mod and aTypeDeclStmt.mod[0] \
                                               or 1
                # extract the name and length for character declarations such as "character foo*7"
                if (isinstance(aDecl, fs._NoInit)
                        or isinstance(aDecl, fs._AssignInit)):
                    if (isinstance(aDecl.lhs, fe.Ops) and aDecl.lhs.op == '*'):
                        DebugManager.debug(
                            '(recognized as a character statement with asterisk length specification) ... ',
                            newLine=False)
                        name = aDecl.lhs.a1
                        newLength = aDecl.lhs.a2
            theSymtabEntry = localSymtab.lookup_name_local(name)
            if isinstance(aDecl, fs._AssignInit):
                theTmpDeclStmt = aTypeDeclStmt.__class__(
                    aTypeDeclStmt.get_mod(), aTypeDeclStmt.get_attrs(),
                    [aDecl.lhs])
            else:
                theTmpDeclStmt = aTypeDeclStmt.__class__(
                    aTypeDeclStmt.get_mod(), aTypeDeclStmt.get_attrs(),
                    [aDecl])
            if theSymtabEntry:  # already in symtab -> enter new information (taking exception to any conflicts)
                DebugManager.debug(
                    'decl "' + str(aDecl) +
                    '" already present in local symbol table as ' +
                    str(theSymtabEntry.debug(name)))
                theSymtabEntry.enterType(newType, localSymtab)
                if (theSymtabEntry.dimensions and (newDimensions is None)):
                    theTmpDeclStmt.dimension = theSymtabEntry.dimensions
                else:
                    theSymtabEntry.enterDimensions(newDimensions)
                theSymtabEntry.enterLength(newLength)
                if (isinstance(aDecl, fs._PointerInit)
                        or isinstance(aDecl, fs._AssignInit)
                        and localSymtab.isConstInit(aDecl.rhs)):
                    theSymtabEntry.enterConstInit(
                        localSymtab.getConstInit(aDecl.rhs))
                if inDrvdTypeDefn:
                    theSymtabEntry.enterDrvdTypeName(inDrvdTypeDefn)
                # for function/subroutine entries, also update this information in the parent symbol table
                if localSymtab.parent and theSymtabEntry.entryKind.__class__ in (
                        SymtabEntry.FunctionEntryKind,
                        SymtabEntry.SubroutineEntryKind
                ) and not (theSymtabEntry.origin == 'external'):
                    parentSymtabEntry = localSymtab.parent.lookup_name_local(
                        name)
                    if (not parentSymtabEntry):
                        localSymtab.replicateEntry(name,
                                                   'local',
                                                   name,
                                                   localSymtab.parent,
                                                   replicatingUp=True)
                        DebugManager.debug(
                            '[Line ' + str(aTypeDeclStmt.lineNumber) +
                            ']: new PARENT unit symtab entry (see above)')
                    else:
                        localSymtab.augmentParentEntry(theSymtabEntry,
                                                       parentSymtabEntry, name)
                        DebugManager.debug(
                            '[Line ' + str(aTypeDeclStmt.lineNumber) +
                            ']: updated PARENT unit symtab entry ' +
                            parentSymtabEntry.debug(name))
                typetab_id = globalTypeTable.getType(theTmpDeclStmt,
                                                     localSymtab)
                theSymtabEntry.typetab_id = typetab_id
            else:  # no symtab entry -> create one
                if aTypeDeclStmt.parameter:
                    newSymtabEntry = SymtabEntry(
                        SymtabEntry.VariableEntryKind(),
                        type=newType,
                        dimensions=newDimensions,
                        length=newLength,
                        origin='local',
                        access=access)
                else:
                    newSymtabEntry = SymtabEntry(
                        SymtabEntry.GenericEntryKind(),
                        type=newType,
                        dimensions=newDimensions,
                        length=newLength,
                        origin='local',
                        access=access)
                if (isinstance(aDecl, fs._PointerInit)
                        or isinstance(aDecl, fs._AssignInit)
                        and localSymtab.isConstInit(aDecl.rhs)):
                    newSymtabEntry.enterConstInit(
                        localSymtab.getConstInit(aDecl.rhs))
                elif aTypeDeclStmt.parameter and isinstance(
                        aDecl, fs._AssignInit):
                    newSymtabEntry.enterConstInit(aDecl.rhs)
                if inDrvdTypeDefn:
                    newSymtabEntry.enterDrvdTypeName(inDrvdTypeDefn)
                localSymtab.enter_name(name, newSymtabEntry)
                typetab_id = globalTypeTable.getType(theTmpDeclStmt,
                                                     localSymtab)
                newSymtabEntry.typetab_id = typetab_id
                DebugManager.debug(
                    'decl "' + str(aDecl) +
                    '" NOT already present in symbol table => adding ' +
                    str(newSymtabEntry.debug(name)))
            unitSymbolEntry = localSymtab.lookup_name_level(curr.val.name())[0]
            if (unitSymbolEntry and isinstance(unitSymbolEntry.entryKind,
                                               SymtabEntry.FunctionEntryKind)
                    and unitSymbolEntry.genericInfo
                    and unitSymbolEntry.genericInfo.genericName):
                genericSymbolEntry = localSymtab.lookup_name(
                    unitSymbolEntry.genericInfo.genericName)
                if (genericSymbolEntry is None):
                    raise SymtabError('cannot find generic ' +
                                      unitSymbolEntry.genericInfo.genericName +
                                      ' for specific ' + curr.val.name() +
                                      ' entry: ' +
                                      unitSymbolEntry.debug(curr.val.name()))
                if (genericSymbolEntry.genericInfo is None
                        or (not curr.val.name().lower()
                            in genericSymbolEntry.genericInfo.resolvableTo)):
                    raise SymtabError(
                        'no info available for specific ' + curr.val.name() +
                        ' in generic entry: ' + genericSymbolEntry.debug(
                            unitSymbolEntry.genericInfo.genericName))
                specificFormalArgs = localSymtab.lookup_name(
                    unitSymbolEntry.genericInfo.genericName
                ).genericInfo.resolvableTo[curr.val.name().lower()]
                if (specificFormalArgs is None):
                    raise SymtabError(
                        'no arguments set for specific ' + curr.val.name() +
                        ' under generic ' +
                        unitSymbolEntry.genericInfo.genericName + ' entry: ' +
                        localSymtab.lookup_name(
                            unitSymbolEntry.genericInfo.genericName).debug(
                                unitSymbolEntry.genericInfo.genericName))
                if name.lower() in specificFormalArgs:
                    se = localSymtab.lookup_name_local(name)
                    specificFormalArgs[name.lower()] = (se.typetab_id,
                                                        se.dimensions)
                    DebugManager.debug('recorded type in ' +
                                       str(id(specificFormalArgs)) +
                                       str(specificFormalArgs))
        except SymtabError, e:  # add lineNumber and symbol name to any SymtabError we encounter
            e.lineNumber = e.lineNumber or aTypeDeclStmt.lineNumber
            e.symbolName = e.symbolName or name
            raise e