blob: 8a3b48efaed657b30e14f05ded7fd559417bec66 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_idlc.hxx"
#include <idlc/astscope.hxx>
#include <idlc/astbasetype.hxx>
#ifndef _IDLC_ASTINERFACE_HXX_
#include <idlc/astinterface.hxx>
#endif
#include <idlc/errorhandler.hxx>
using namespace ::rtl;
sal_Bool isGlobal(const OString& scopedName)
{
if ((scopedName.getLength() == 0) || (scopedName.indexOf(':') == 0))
{
return sal_True;
}
return sal_False;
}
AstScope::AstScope(NodeType nodeType)
: m_nodeType(nodeType)
{
}
AstScope::~AstScope()
{
}
AstDeclaration* AstScope::addDeclaration(AstDeclaration* pDecl)
{
AstDeclaration* pDeclaration = NULL;
if ((pDeclaration = lookupForAdd(pDecl)) != NULL)
{
if (pDecl->getNodeType() == NT_union_branch )
{
m_declarations.push_back(pDecl);
return pDecl;
}
if ( pDecl->hasAncestor(pDeclaration) )
{
idlc()->error()->error2(EIDL_REDEF_SCOPE, pDecl, pDeclaration);
return NULL;
}
if ( (pDecl->getNodeType() == pDeclaration->getNodeType()) &&
(pDecl->getNodeType() == NT_sequence
|| pDecl->getNodeType() == NT_array
|| pDecl->getNodeType() == NT_instantiated_struct) )
{
return pDeclaration;
}
if ( (pDeclaration->getNodeType() == NT_interface)
&& (pDecl->getNodeType() == NT_interface)
&& !((AstInterface*)pDeclaration)->isDefined() )
{
m_declarations.push_back(pDecl);
return pDecl;
}
if ( (NT_service == m_nodeType) &&
( ((pDecl->getNodeType() == NT_interface_member)
&& (pDeclaration->getNodeType() == NT_interface)) ||
((pDecl->getNodeType() == NT_service_member)
&& (pDeclaration->getNodeType() == NT_service)) )
)
{
m_declarations.push_back(pDecl);
return pDecl;
}
idlc()->error()->error2(EIDL_REDEF_SCOPE, scopeAsDecl(this), pDecl);
return NULL;
}
m_declarations.push_back(pDecl);
return pDecl;
}
sal_uInt16 AstScope::getNodeCount(NodeType nodeType)
{
DeclList::const_iterator iter = getIteratorBegin();
DeclList::const_iterator end = getIteratorEnd();
AstDeclaration* pDecl = NULL;
sal_uInt16 count = 0;
while ( iter != end )
{
pDecl = *iter;
if ( pDecl->getNodeType() == nodeType )
count++;
++iter;
}
return count;
}
AstDeclaration* AstScope::lookupByName(const OString& scopedName)
{
AstDeclaration* pDecl = NULL;
AstScope* pScope = NULL;
if (scopedName.getLength() == 0)
return NULL;
// If name starts with "::" start look up in global scope
if ( isGlobal(scopedName) )
{
pDecl = scopeAsDecl(this);
if ( !pDecl )
return NULL;
pScope = pDecl->getScope();
// If this is the global scope ...
if ( !pScope )
{
// look up the scopedName part after "::"
OString subName = scopedName.copy(2);
pDecl = lookupByName(subName);
return pDecl;
//return pScope->lookupByName();
}
// OK, not global scope yet, so simply iterate with parent scope
pDecl = pScope->lookupByName(scopedName);
return pDecl;
}
// The name does not start with "::"
// Look up in the local scope and start with the first scope
sal_Int32 nIndex = scopedName.indexOf(':');
OString firstScope = nIndex > 0 ? scopedName.copy(0, nIndex) : scopedName;
sal_Bool bFindFirstScope = sal_True;
pDecl = lookupByNameLocal(firstScope);
if ( !pDecl )
{
bFindFirstScope = sal_False;
// OK, not found. Go down parent scope chain
pDecl = scopeAsDecl(this);
if ( pDecl )
{
pScope = pDecl->getScope();
if ( pScope )
pDecl = pScope->lookupByName(scopedName);
else
pDecl = NULL;
// Special case for scope which is an interface. We
// have to look in the inherited interfaces as well.
if ( !pDecl )
{
if (m_nodeType == NT_interface)
pDecl = lookupInInherited(scopedName);
}
}
}
if ( bFindFirstScope && (firstScope != scopedName) )
{
sal_Int32 i = 0;
sal_Int32 nOffset = 2;
do
{
pScope = declAsScope(pDecl);
if( pScope )
{
pDecl = pScope->lookupByNameLocal(scopedName.getToken(nOffset, ':', i ));
nOffset = 1;
}
if( !pDecl )
break;
} while( i != -1 );
if ( !pDecl )
{
// last try if is not the global scope and the scopeName isn't specify global too
pDecl = scopeAsDecl(this);
if ( pDecl && (pDecl->getLocalName() != "") )
{
pScope = pDecl->getScope();
if ( pScope )
pDecl = pScope->lookupByName(scopedName);
} else
{
pDecl = NULL;
}
}
}
return pDecl;
}
AstDeclaration* AstScope::lookupByNameLocal(const OString& name) const
{
DeclList::const_iterator iter(m_declarations.begin());
DeclList::const_iterator end(m_declarations.end());
AstDeclaration* pDecl = NULL;
while ( iter != end )
{
pDecl = *iter;
if ( pDecl->getLocalName() == name )
return pDecl;
++iter;
}
return NULL;
}
AstDeclaration* AstScope::lookupInInherited(const OString& scopedName) const
{
AstInterface* pInterface = (AstInterface*)this;
if ( !pInterface )
return NULL;
// Can't look in an interface which was not yet defined
if ( !pInterface->getScope() )
{
idlc()->error()->forwardLookupError(pInterface, scopedName);
}
// OK, loop through inherited interfaces. Stop when you find it
AstInterface::InheritedInterfaces::const_iterator iter(
pInterface->getAllInheritedInterfaces().begin());
AstInterface::InheritedInterfaces::const_iterator end(
pInterface->getAllInheritedInterfaces().end());
while ( iter != end )
{
AstInterface const * resolved = iter->getResolved();
AstDeclaration* pDecl = resolved->lookupByNameLocal(scopedName);
if ( pDecl )
return pDecl;
pDecl = resolved->lookupInInherited(scopedName);
if ( pDecl )
return pDecl;
++iter;
}
// Not found
return NULL;
}
AstDeclaration* AstScope::lookupPrimitiveType(ExprType type)
{
AstDeclaration* pDecl = NULL;
AstScope* pScope = NULL;
AstBaseType* pBaseType = NULL;
OString typeName;
pDecl = scopeAsDecl(this);
if ( !pDecl )
return NULL;
pScope = pDecl->getScope();
if ( pScope)
return pScope->lookupPrimitiveType(type);
switch (type)
{
case ET_none:
OSL_ASSERT(false);
break;
case ET_short:
typeName = OString("short");
break;
case ET_ushort:
typeName = OString("unsigned short");
break;
case ET_long:
typeName = OString("long");
break;
case ET_ulong:
typeName = OString("unsigned long");
break;
case ET_hyper:
typeName = OString("hyper");
break;
case ET_uhyper:
typeName = OString("unsigned hyper");
break;
case ET_float:
typeName = OString("float");
break;
case ET_double:
typeName = OString("double");
break;
case ET_char:
typeName = OString("char");
break;
case ET_byte:
typeName = OString("byte");
break;
case ET_boolean:
typeName = OString("boolean");
break;
case ET_any:
typeName = OString("any");
break;
case ET_void:
typeName = OString("void");
break;
case ET_type:
typeName = OString("type");
break;
case ET_string:
typeName = OString("string");
break;
}
pDecl = lookupByNameLocal(typeName);
if ( pDecl && (pDecl->getNodeType() == NT_predefined) )
{
pBaseType = (AstBaseType*)pDecl;
if ( pBaseType->getExprType() == type )
return pDecl;
}
return NULL;
}
AstDeclaration* AstScope::lookupForAdd(AstDeclaration* pDecl)
{
if ( !pDecl )
return NULL;
AstDeclaration* pRetDecl = lookupByNameLocal(pDecl->getLocalName());
return pRetDecl;
}