blob: 38005e1ef649448962c069befb2f165f2077364b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 University of Illinois at Urbana-Champaign and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.photran.internal.core.analysis.binding;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.photran.internal.core.analysis.binding.Definition.Visibility;
import org.eclipse.photran.internal.core.analysis.loops.ASTVisitorWithLoops;
import org.eclipse.photran.internal.core.analysis.types.Type;
import org.eclipse.photran.internal.core.lexer.Token;
import org.eclipse.photran.internal.core.vpg.PhotranTokenRef;
import org.eclipse.photran.internal.core.vpg.PhotranVPG;
import org.eclipse.photran.internal.core.vpg.PhotranVPGWriter;
/**
* Abstract superclass providing utility methods for several visitor classes
* that collect bindings in an AST. See subclasses and {@link Binder}.
*
* @author Jeff Overbey
* @see Binder
*/
public abstract class BindingCollector extends ASTVisitorWithLoops
{
protected PhotranVPG vpg = PhotranVPG.getInstance();
protected PhotranVPGWriter vpgProvider = PhotranVPG.getProvider();
protected void markSubprogramExport(IFile file, Token subprogramName)
{
vpgProvider.markFileAsExportingSubprogram(file, subprogramName.getText());
}
protected void markSubprogramImport(IFile file, Token subprogramName)
{
vpgProvider.markFileAsImportingSubprogram(file, subprogramName.getText());
}
protected void markModuleExport(IFile file, Token moduleName)
{
vpgProvider.markFileAsExportingModule(file, moduleName.getText());
}
protected void setScopeDefaultVisibilityToPrivate(ScopingNode scope)
{
vpgProvider.setDefaultScopeVisibilityToPrivate(scope);
}
protected void setDefinition(Token ident, Definition def)
{
vpgProvider.setDefinitionFor(ident.getTokenRef(), def);
}
// addDefinition() and bindRenamedEntity() accept null to support the module loader
// (its code is cleaner if it doesn't have to special-case nulls)
/**
* @param definitionIsInOuterScope For example, SubroutineStmt nodes are contained within SubroutineSubprogram nodes. However,
* the subroutine they declare is not a member of its own scope: it is a member of the outer scope. Set this parameter to true
* in this case.
*/
Definition addDefinition(Token token, Definition.Classification classification, Type type)
{
if (token == null) return null;
try
{
ScopingNode enclosingScope = token.getEnclosingScope();
Visibility visibility = enclosingScope.isDefaultVisibilityPrivate() ? Visibility.PRIVATE : Visibility.PUBLIC;
Definition definition = new Definition(token.getText(), token.getTokenRef(), classification, /*visibility,*/ type);
vpgProvider.setDefinitionFor(token.getTokenRef(), definition);
vpgProvider.markScope(token.getTokenRef(), enclosingScope);
vpgProvider.markDefinitionVisibilityInScope(token.getTokenRef(), enclosingScope, visibility);
checkForIllegalShadowing(token.getText(), token.getTokenRef(), enclosingScope);
return definition;
}
catch (Exception e)
{
throw new Error(e);
}
}
protected void checkForIllegalShadowing(String name, PhotranTokenRef tokenRef, ScopingNode enclosingScope)
{
if (enclosingScope.isMainProgram() || enclosingScope.isSubprogram() || enclosingScope.isModule())
{
// Force resolution in case this is a post-transform analysis and the scope has been renamed
String scopeName = enclosingScope.getName();
if (scopeName != null &&
PhotranVPG.canonicalizeIdentifier(name).equals(
PhotranVPG.canonicalizeIdentifier(scopeName)))
{
vpgProvider.markIllegalShadowing(tokenRef, enclosingScope.getNameToken().getTokenRef());
}
}
}
// Definition addDefinitionAndDuplicateInLocalScope(Token name, Classification classification, Type type)
// {
// Definition result = addDefinition(name, classification, type);
// // addDefinition called vpg.markScope for the enclosing scope
//
// ScopingNode localScope = name.findNearestAncestor(ScopingNode.class);
// vpg.markScope(name.getTokenRef(), localScope);
//
// return result;
// }
Definition addDefinition(Token token, Definition.Classification classification)
{
return addDefinition(token, classification, Type.VOID);
}
void importDefinition(Definition definitionToImport, ScopingNode importIntoScope)
{
try
{
vpgProvider.markScope(definitionToImport.getTokenRef(), importIntoScope);
if (importIntoScope.isDefaultVisibilityPrivate())
vpgProvider.markDefinitionVisibilityInScope(definitionToImport.getTokenRef(), importIntoScope, Visibility.PRIVATE);
checkForIllegalShadowing(definitionToImport.getCanonicalizedName(), definitionToImport.getTokenRef(), importIntoScope);
}
catch (Exception e)
{
throw new Error(e);
}
}
List<PhotranTokenRef> bind(Token identifier)
{
List<PhotranTokenRef> result = identifier.manuallyResolveBinding();
for (PhotranTokenRef def : result)
bind(identifier, def);
return result;
}
List<PhotranTokenRef> bindNoImplicits(Token identifier)
{
List<PhotranTokenRef> result = identifier.manuallyResolveBindingNoImplicits();
for (PhotranTokenRef def : result)
bind(identifier, def);
return result;
}
List<PhotranTokenRef> bindAsParam(Token identifier)
{
List<PhotranTokenRef> result = bind(identifier);
for (PhotranTokenRef def : result)
{
Definition d = vpg.getDefinitionFor(def);
d.markAsSubprogramArgument();
vpgProvider.setDefinitionFor(def, d);
}
return result;
}
void bind(Token identifier, PhotranTokenRef toDefinition)
{
try
{
vpgProvider.markBinding(identifier.getTokenRef(), toDefinition);
}
catch (Exception e)
{
throw new Error(e);
}
}
void bindRenamedEntity(Token identifier, PhotranTokenRef toDefinition)
{
if (identifier == null) return;
try
{
vpgProvider.markRenamedBinding(identifier.getTokenRef(), toDefinition);
}
catch (Exception e)
{
throw new Error(e);
}
}
void dontbind(Token identifier)
{
// A derived type component or subroutine parameter name was found;
// don't attempt to bind it, since this would require type checking
}
}