VariableReferenceValue.java
package edu.udel.cis.vsl.tass.dynamic.impl.value;
import edu.udel.cis.vsl.tass.dynamic.IF.cell.CellIF;
import edu.udel.cis.vsl.tass.dynamic.IF.cell.HeapCellIF;
import edu.udel.cis.vsl.tass.dynamic.IF.cell.LocalCellIF;
import edu.udel.cis.vsl.tass.dynamic.IF.cell.ProcessCellIF;
import edu.udel.cis.vsl.tass.dynamic.IF.cell.SharedCellIF;
import edu.udel.cis.vsl.tass.dynamic.IF.type.ReferenceValueTypeIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.ValueIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.VariableReferenceValueIF;
import edu.udel.cis.vsl.tass.dynamic.impl.type.ValueTypeFactory;
import edu.udel.cis.vsl.tass.model.IF.ProcessIF;
import edu.udel.cis.vsl.tass.model.IF.scope.LocalScopeIF;
import edu.udel.cis.vsl.tass.model.IF.variable.LocalVariableIF;
import edu.udel.cis.vsl.tass.morph.Morphic;
// question: is initial value part of the state of this object?
// why do two instances have to have same initial value?
// answer: this is the initial value before any initialization expression
// is evaluated and assigned to the variable. Hence it is either "undefined"
// or a symbolic constant because it is an input variable.
/**
* Represents a reference to a variable. The variable is an instance of CellIF,
* i.e., a dynamic variable. There is also an integer-valued symbolic
* expression, the "offset". This is technically either 0 or 1. It is there
* because it is possible in C to have a pointer to the position just after a
* variable, as in
*
* double x; double *p = (&x) + 1;
*
* However, an attempt to dereference a reference value for which the offset if
* not 0 will result in an execution exception.
*
* The initial value for the variable can be cached here for convenience, so it
* does not have to be re-computed repeatedly.
*/
public class VariableReferenceValue extends ReferenceValue implements
VariableReferenceValueIF {
private static int classHashCode = VariableReferenceValue.class.hashCode();
private CellIF cell;
/**
* Extrinsic data: like the undefined value, the initialValue can only be
* cached if the type is committed.
*/
// TODO: this is never used:
private ValueIF initialValue = null;
/**
* This can be 0 or 1. 0 means a pointer to the variable, as you would
* expect. 1 means a pointer to the point just after the variable, which is
* the result of pointer arithmetic in which "1" was added to the original
* variable pointer. This is a legal pointer value, but cannot be
* dereferenced.
*/
private ValueIF offset;
public VariableReferenceValue(CellIF variable,
ReferenceValueTypeIF valueType, ValueIF offset) {
super(null, valueType);
if (variable == null)
throw new NullPointerException("null variable");
this.cell = variable;
if (offset == null)
throw new NullPointerException("null offset");
this.offset = offset;
}
@Override
protected int computeHashCode() {
return super.computeHashCode() + classHashCode + cell.hashCode()
+ offset.hashCode();
}
public String fullName() {
if (cell instanceof LocalCellIF) {
LocalVariableIF localVariable = ((LocalCellIF) cell).variable();
int stackPosition = ((LocalCellIF) cell).stackIndex();
LocalScopeIF scope = localVariable.scope();
int mid = localVariable.model().id();
int pid = scope.function().process().pid();
int fid = scope.function().idInScope();
int scopeId = scope.localId();
int vid = localVariable.idInScope();
return "m" + mid + "p" + pid + "s" + stackPosition + "f" + fid
+ "c" + scopeId + "v" + vid;
} else if (cell instanceof SharedCellIF) {
SharedCellIF sharedCell = (SharedCellIF) cell;
return "m" + sharedCell.variable().model().id() + "v"
+ sharedCell.sharedVariableId();
} else if (cell instanceof ProcessCellIF) {
ProcessCellIF processCell = (ProcessCellIF) cell;
ProcessIF process = processCell.variable().scope().process();
return "m" + process.model().id() + "p" + process.pid() + "v"
+ processCell.processVariableId();
} else if (cell instanceof HeapCellIF) {
HeapCellIF dynamicHeapVariable = (HeapCellIF) cell;
ProcessIF process = dynamicHeapVariable.process();
int heapIndex = dynamicHeapVariable.heapIndex();
return "m" + process.model().id() + "p" + process.pid() + "h"
+ heapIndex;
}
throw new RuntimeException("Unknown dynamic variable type:\n" + cell);
}
public CellIF variable() {
return cell;
}
public ValueIF offset() {
return offset;
}
public String toString() {
String result = "&" + cell;
String offsetString = offset.toString();
if (!"0".equals(offsetString))
result += "+" + offsetString;
return result;
}
public VariableReferenceValueIF variableReference() {
return this;
}
@Override
public boolean computeEquals(Morphic component) {
if (!super.computeEquals(component))
return false;
if (component instanceof VariableReferenceValue) {
VariableReferenceValue that = (VariableReferenceValue) component;
return cell.equals(that.cell) && offset.equals(that.offset);
}
return false;
}
@Override
public boolean isNull() {
return false;
}
@Override
protected void commitChildren() {
super.commit();
if (initialValue != null)
initialValue.commit();
}
@Override
protected void canonicalizeChildren(ValueFactory valueFactory,
ValueTypeFactory typeFactory) {
super.canonicalizeChildren(valueFactory, typeFactory);
offset = valueFactory.canonic(offset);
if (initialValue != null)
initialValue = valueFactory.canonic(initialValue);
}
}