CommonScope.java
/**
*
*/
package edu.udel.cis.vsl.civl.model.common;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import edu.udel.cis.vsl.civl.model.IF.Function;
import edu.udel.cis.vsl.civl.model.IF.Identifier;
import edu.udel.cis.vsl.civl.model.IF.Scope;
import edu.udel.cis.vsl.civl.model.IF.type.ArrayType;
import edu.udel.cis.vsl.civl.model.IF.type.ProcessType;
import edu.udel.cis.vsl.civl.model.IF.type.Type;
import edu.udel.cis.vsl.civl.model.IF.variable.Variable;
/**
* A scope.
*
* @author Timothy K. Zirkel (zirkel)
*
*/
public class CommonScope implements Scope {
private Scope parent;
private Variable[] variables;
private Set<Scope> children = new HashSet<Scope>();
private Collection<Variable> procRefs = new HashSet<Variable>();
private int id;
private Function function;
/**
* A scope.
*
* @param parent
* The containing scope of this scope. Only null for the
* outermost scope of the designated "System" function.
*
* @param variables
* The set of variables in this scope.
*/
public CommonScope(Scope parent, Set<Variable> variables, int id) {
this.parent = parent;
this.variables = new Variable[variables.size()];
for (Variable v : variables) {
assert this.variables[v.vid()] == null;
this.variables[v.vid()] = v;
v.setScope(this);
checkProcRef(v);
}
this.id = id;
}
/**
* @return The containing scope of this scope.
*/
public Scope parent() {
return parent;
}
/**
* @return The set of variables contained in this scope.
*/
public Set<Variable> variables() {
return new LinkedHashSet<Variable>(Arrays.asList(variables));
}
/**
* @return The number of variables contained in this scope.
*/
public int numVariables() {
return variables.length;
}
/**
* @return Get the variable at position i.
*/
public Variable getVariable(int i) {
return variables[i];
}
/**
* @return The id of this scope.
*/
public int id() {
return id;
}
/**
* @return The scopes contained by this scope.
*/
public Set<Scope> children() {
return children;
}
/**
* @param parent
* The containing scope of this scope.
*/
public void setParent(Scope parent) {
this.parent = parent;
}
/**
* @param variables
* The set of variables contained in this scope.
*/
public void setVariables(Set<Variable> variables) {
this.variables = new Variable[variables.size()];
for (Variable v : variables) {
assert this.variables[v.vid()] == null;
this.variables[v.vid()] = v;
checkProcRef(v);
}
}
/**
* @param children
* The scopes contained by this scope.
*/
public void setChildren(Set<Scope> children) {
this.children = children;
}
/**
* @param A
* new scope contained by this scope.
*/
public void addChild(Scope child) {
children.add(child);
}
/**
* A new variable in this scope.
*/
public void addVariable(Variable variable) {
Variable[] oldVariables = variables;
variables = new Variable[oldVariables.length + 1];
for (int i = 0; i < oldVariables.length; i++) {
variables[i] = oldVariables[i];
}
assert variable.vid() == oldVariables.length;
variables[oldVariables.length] = variable;
checkProcRef(variable);
variable.setScope(this);
}
/**
* Get the variable associated with an identifier. If this scope does not
* contain such a variable, parent scopes will be recursively checked.
*
* @param name
* The identifier for the variable.
* @return The model representation of the variable in this scope hierarchy,
* or null if not found.
*/
public Variable variable(Identifier name) {
for (Variable v : variables) {
if (v.name().equals(name)) {
return v;
}
}
if (parent != null) {
return parent.variable(name);
}
return null;
}
/**
* Get the variable at the specified array index.
*
* @param vid
* The index of the variable. Should be in the range
* [0,numVariable()-1].
* @return The variable at the index.
*/
public Variable variable(int vid) {
return variables[vid];
}
/**
* @param function
* The function containing this scope.
*/
public void setFunction(Function function) {
this.function = function;
}
/**
* @return The function containing this scope.
*/
public Function function() {
return function;
}
/**
* @return The identifier of the function containing this scope.
*/
public Identifier functionName() {
return function.name();
}
/**
* A variables has a "procRefType" if it is of type Process or if it is an
* array with element of procRefType.
*
* @return A collection of the variables in this scope with a procRefType.
*/
public Collection<Variable> variablesWithProcrefs() {
return procRefs;
}
/**
* Checks if a variables is a procRefType. If it is, it gets added to
* procRefs.
*
* @param v
* The variable being checked.
*/
private void checkProcRef(Variable variable) {
boolean procRefType = false;
if (variable.type() instanceof ProcessType) {
procRefType = true;
} else if (variable.type() instanceof ArrayType) {
Type baseType = ((ArrayType) variable.type()).baseType();
while (baseType instanceof ArrayType) {
baseType = ((ArrayType) baseType).baseType();
}
if (baseType instanceof ProcessType) {
procRefType = true;
}
}
if (procRefType) {
procRefs.add(variable);
}
}
@Override
public String toString() {
String result = "Variables : {";
for (int i = 0; i < variables.length; i++) {
if (i != 0) {
result += ", ";
}
result += variables[i].toString();
}
result += "}";
return result;
}
/**
* Print the scope and all children.
*
* @param prefix
* String prefix to print on each line
* @param out
* The PrintStream to use for printing.
*/
public void print(String prefix, PrintStream out) {
String parentID = "";
if (parent == null) {
parentID += "null";
} else {
parentID += parent.id();
}
out.println(prefix + "scope " + id + " (parent: " + parentID + ")");
for (Variable v : variables) {
out.println(prefix + "| " + v);
}
for (Scope child : children) {
if (child.function().equals(function)) {
child.print(prefix + "| ", out);
}
}
out.flush();
}
public int getVid(Variable staticVariable) {
int result = -1;
for (int i = 0; i < variables.length; i++) {
if (variables[i].equals(staticVariable)) {
result = i;
break;
}
}
// TODO If not found, either throw error here or catch higher up
return result;
}
}