package de.skuzzle.polly.core.parser.ast.declarations;
import java.util.ArrayList;
import java.util.Collection;
import de.skuzzle.polly.core.parser.Position;
import de.skuzzle.polly.core.parser.ast.Identifier;
import de.skuzzle.polly.core.parser.ast.Node;
import de.skuzzle.polly.core.parser.ast.declarations.types.Type;
import de.skuzzle.polly.core.parser.ast.expressions.Expression;
import de.skuzzle.polly.core.parser.ast.expressions.VarAccess;
import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversal;
import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversalException;
import de.skuzzle.polly.core.parser.ast.visitor.ASTVisitor;
import de.skuzzle.polly.core.parser.ast.visitor.Transformation;
import de.skuzzle.polly.tools.Equatable;
/**
* Base class for declarations. They must have at least a name and a {@link Position}.
* During type checking, a declaration may get assigned a {@link Type}. Two declarations
* are considered equal, if their names are equal and their types a compatible as
* determined by {@link Type#equals(Object)}.
*
* @author Simon Taddiken
*/
public class Declaration extends Node implements Comparable<Declaration> {
private final Identifier name;
private boolean isPublic;
private boolean isTemp;
private boolean isNative;
private boolean isLocal;
private final Expression expression;
private final Collection<VarAccess> usage;
public Declaration(Position position, Identifier name, Expression expression) {
this(position, name, expression, false);
}
public Declaration(Position position, Identifier name, Expression expression,
boolean local) {
super(position);
this.name = name;
this.expression = expression;
this.usage = new ArrayList<VarAccess>();
this.isLocal = local;
}
/**
* Whether this declarations belongs to a formal parameter of a function
*
* @return Whether this is a local declaration.
*/
public boolean isLocal() {
return this.isLocal;
}
/**
* Returns whether this declaration is accessed anywhere.
*
* @return Whether this declaration is accessed anywhere.
*/
public boolean isUnused() {
return this.usage.isEmpty();
}
/**
* Gets the type of this declaration.
*
* @return The type.
*/
public Type getType() {
return this.expression.getUnique();
}
/**
* Gets the declared expression.
*
* @return The expression.
*/
public Expression getExpression() {
return this.expression;
}
/**
* Gets the name of this declaration.
*
* @return The name.
*/
public Identifier getName() {
return this.name;
}
/**
* Gets whether this is a public declaration.
*
* @return Whether this is a public declaration.
*/
public boolean isPublic() {
return this.isPublic;
}
/**
* Sets whether this is a public declaration. This will only have a practical effect
* when being set before this declaration is declared in a {@link Namespace}.
*
* @param isPublic Whether this is a public declaration.
*/
public void setPublic(boolean isPublic) {
this.isPublic = isPublic;
}
@Deprecated
public boolean isTemp() {
return this.isTemp;
}
public void setTemp(boolean isTemp) {
this.isTemp = isTemp;
}
/**
* Gets whether this is a primitive delcaration.
*
* @return Whether this is a primitive declaration.
*/
public boolean isNative() {
return this.isNative;
}
/**
* Sets whether this is a native declaration. Native delcarations are those,
* that are hardcoded into polly (mostly created by {@link Function} subclasses).
* Those declarations are not stored to file.
*
* @param isNative Whether this is a native declaration.
*/
public void setNative(boolean isNative) {
this.isNative = isNative;
}
/**
* Gets all AST nodes that may have access to this declaration.
*
* @return Collection of VarAccess's.
*/
public Collection<VarAccess> getUsage() {
return this.usage;
}
@Override
public Class<?> getEquivalenceClass() {
return Declaration.class;
}
@Override
public boolean actualEquals(Equatable o) {
final Declaration other = (Declaration) o;
return this.name.equals(other.name) && this.getType().equals(other.getType());
}
@Override
public int compareTo(Declaration o) {
// order by length, then lexically
final String thisId = this.getName().getId();
final String otherId = o.getName().getId();
final int lengthComp = Integer.compare(thisId.length(), otherId.length());
return lengthComp != 0 ? lengthComp :
this.name.getId().compareTo(o.getName().getId());
}
/**
* Callback method which is called when a declaration is looked up.
*
* @param access The {@link VarAccess} expression in the AST.
*/
protected void onLookup(VarAccess access) {
this.usage.add(access);
}
@Override
public String toString() {
return this.name + " [Type: " + this.getType() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public boolean visit(ASTVisitor visitor) throws ASTTraversalException {
return visitor.visit(this);
}
@Override
public boolean traverse(ASTTraversal visitor) throws ASTTraversalException {
switch (visitor.before(this)) {
case ASTTraversal.SKIP: return true;
case ASTTraversal.ABORT: return false;
}
if (!this.name.traverse(visitor)) {
return false;
}
if (!this.expression.traverse(visitor)) {
return false;
}
return visitor.after(this) == ASTTraversal.CONTINUE;
}
@Override
public Declaration transform(Transformation transformation) throws ASTTraversalException {
return transformation.transformDeclaration(this);
}
}