CommonScope.java
package edu.udel.cis.vsl.abc.ast.entity.common;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import edu.udel.cis.vsl.abc.ast.IF.AST;
import edu.udel.cis.vsl.abc.ast.entity.IF.Entity;
import edu.udel.cis.vsl.abc.ast.entity.IF.Entity.EntityKind;
import edu.udel.cis.vsl.abc.ast.entity.IF.Function;
import edu.udel.cis.vsl.abc.ast.entity.IF.Label;
import edu.udel.cis.vsl.abc.ast.entity.IF.OrdinaryEntity;
import edu.udel.cis.vsl.abc.ast.entity.IF.Scope;
import edu.udel.cis.vsl.abc.ast.entity.IF.TaggedEntity;
import edu.udel.cis.vsl.abc.ast.entity.IF.Variable;
import edu.udel.cis.vsl.abc.ast.node.IF.ASTNode;
import edu.udel.cis.vsl.abc.token.IF.SyntaxException;
import edu.udel.cis.vsl.abc.token.IF.UnsourcedException;
public class CommonScope implements Scope {
private ScopeKind scopeKind;
/**
* The root node of this scope in the AST. Used only for printing as a way
* to identify the scope easily.
*/
private ASTNode root;
private int id = -1;
private AST translationUnit;
private CommonScope parentScope;
private ArrayList<Scope> children = new ArrayList<Scope>();
private Set<String> functionNames = new HashSet<>();
/**
* Contains an entry for each ordinary entity declared in this scope that is
* NOT anonymous (i.e., has a non-null name).
*/
private Map<String, OrdinaryEntity> ordinaryEntityMap = new LinkedHashMap<String, OrdinaryEntity>();
/**
* Contains an entry for each ordinary entity declared in this scope
* (including the anonymous ones).
*/
private ArrayList<OrdinaryEntity> ordinaryEntityList = new ArrayList<OrdinaryEntity>();
private ArrayList<Variable> variableList = new ArrayList<Variable>();
private ArrayList<Function> functionList = new ArrayList<Function>();
/**
* Contains an entry for each tagged entity declared in this scope that is
* NOT anonymous (i.e., has a non-null tag).
*/
private Map<String, TaggedEntity> taggedEntityMap = new LinkedHashMap<String, TaggedEntity>();;
/**
* Contains an entry for each tagged entity declared in this scope
* (including the anonymous ones).
*/
private ArrayList<TaggedEntity> taggedEntityList = new ArrayList<TaggedEntity>();
private Map<String, Label> labelMap = new LinkedHashMap<String, Label>();
private ArrayList<Label> labelList = new ArrayList<Label>();
private int scopeDepth;
public CommonScope(ScopeKind kind, CommonScope parent, ASTNode root) {
this.scopeKind = kind;
this.parentScope = parent;
if (parent != null) {
parent.addChild(this);
scopeDepth = parent.scopeDepth + 1;
} else {
scopeDepth = 0;
}
this.root = root;
}
@Override
public ScopeKind getScopeKind() {
return scopeKind;
}
@Override
public AST getAST() {
return translationUnit;
}
@Override
public CommonScope getParentScope() {
return parentScope;
}
@Override
public int getNumChildrenScopes() {
return children.size();
}
@Override
public Scope getChildScope(int scopeId) {
return children.get(scopeId);
}
@Override
public Iterator<Scope> getChildrenScopes() {
return children.iterator();
}
void addChild(Scope child) {
children.add(child);
}
@Override
public int getScopeDepth() {
return scopeDepth;
}
@Override
public int add(OrdinaryEntity entity) throws UnsourcedException {
EntityKind kind = entity.getEntityKind();
String name = entity.getName(); // may be null
int result = ordinaryEntityList.size();
if (name != null) {
Entity oldEntity = ordinaryEntityMap.get(name);
if (oldEntity != null)
throw new UnsourcedException(
"Entity with same name already exists "
+ "in this scope: " + oldEntity);
ordinaryEntityMap.put(name, entity);
}
ordinaryEntityList.add(entity);
switch (kind) {
case VARIABLE:
variableList.add((Variable) entity);
break;
case FUNCTION:
functionList.add((Function) entity);
break;
default:
}
return result;
}
@Override
public OrdinaryEntity getOrdinaryEntity(boolean isType, String name) {
OrdinaryEntity entity = ordinaryEntityMap.get(name);
if (entity != null && isType
&& entity.getEntityKind() != EntityKind.TYPEDEF)
return null;
return entity;
}
@Override
public OrdinaryEntity getLexicalOrdinaryEntity(boolean isType,
String name) {
for (Scope scope = this; scope != null; scope = scope
.getParentScope()) {
OrdinaryEntity result = scope.getOrdinaryEntity(isType, name);
if (result != null)
return result;
}
return null;
}
@Override
public int getNumVariables() {
return variableList.size();
}
@Override
public Variable getVariable(int variableId) {
return variableList.get(variableId);
}
@Override
public Iterable<Variable> getVariables() {
return variableList;
}
@Override
public int getNumFunctions() {
return functionList.size();
}
@Override
public Function getFunction(int functionId) {
return functionList.get(functionId);
}
@Override
public Iterable<Function> getFunctions() {
return functionList;
}
@Override
public int add(TaggedEntity entity) throws SyntaxException {
String name = entity.getName();
int result = taggedEntityList.size();
if (name != null) {
TaggedEntity oldEntity = taggedEntityMap.get(name);
if (oldEntity != null)
throw new SyntaxException(
"Tagged entity with name " + name + " already exists "
+ "in this scope: "
+ oldEntity.getDeclaration(0).getSource(),
entity.getDeclaration(0).getSource());
taggedEntityMap.put(name, entity);
}
taggedEntityList.add(entity);
return result;
}
@Override
public TaggedEntity getTaggedEntity(String tag) {
return taggedEntityMap.get(tag);
}
@Override
public TaggedEntity getLexicalTaggedEntity(String tag) {
for (Scope scope = this; scope != null; scope = scope
.getParentScope()) {
TaggedEntity result = scope.getTaggedEntity(tag);
if (result != null)
return result;
}
return null;
}
// Labels...
@Override
public int add(Label label) throws UnsourcedException {
String name = label.getName();
Entity oldEntity = labelMap.get(name);
int result = labelList.size();
if (oldEntity != null)
throw new UnsourcedException("Label with same name already exists "
+ "in this scope: " + oldEntity);
labelList.add(label);
labelMap.put(name, label);
return result;
}
@Override
public boolean contains(Label label) {
return getLabel(label.getName()) != null;
}
@Override
public Label getLabel(String name) {
return labelMap.get(name);
}
@Override
public Label getLexicalLabel(String name) {
for (Scope scope = this; scope != null; scope = scope
.getParentScope()) {
Label result = scope.getLabel(name);
if (result != null)
return result;
}
return null;
}
@Override
public Iterator<Label> getLabels() {
return labelList.iterator();
}
@Override
public int getNumLabels() {
return labelList.size();
}
@Override
public Label getLabel(int labelId) {
return labelList.get(labelId);
}
@Override
public int getId() {
return id;
}
@Override
public void setId(int id) {
this.id = id;
}
public String toStringLong() {
String result = "Scope[id=" + id + ", " + scopeKind;
if (parentScope != null)
result += ", parent=" + parentScope.id;
result += ", root=" + root.id() + "]";
return result;
}
@Override
public String toString() {
return toStringLong();
}
@Override
public void print(String prefix, PrintStream out) {
out.println(prefix + toString());
if (!ordinaryEntityList.isEmpty()) {
out.println(prefix + "| ordinary entities");
for (OrdinaryEntity entity : ordinaryEntityList) {
out.println(prefix + "| | " + entity);
}
}
if (!taggedEntityList.isEmpty()) {
out.println(prefix + "| tagged entities");
for (TaggedEntity entity : taggedEntityList) {
out.println(prefix + "| | " + entity);
}
}
if (!labelList.isEmpty()) {
out.println(prefix + "| labels");
for (Label label : labelList) {
out.println(prefix + "| | " + label);
}
}
if (!children.isEmpty()) {
out.println(prefix + "| children scopes");
for (Scope child : children) {
child.print(prefix + "| | ", out);
}
}
out.flush();
}
@Override
public boolean isDescendantOf(Scope that) {
for (Scope scope = this; scope != null; scope = scope.getParentScope())
if (scope == that)
return true;
return false;
}
@Override
public void print(PrintStream out) {
print("", out);
}
@Override
public Iterable<OrdinaryEntity> getOrdinaryEntities() {
return ordinaryEntityList;
}
@Override
public Iterable<TaggedEntity> getTaggedEntities() {
return taggedEntityList;
}
@Override
public Set<String> getFunctionNames() {
return functionNames;
}
@Override
public boolean addFunctionName(String name) {
return functionNames.add(name);
}
}