CommonStructOrUnionLiteralExpression.java
package edu.udel.cis.vsl.civl.model.common.expression;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import edu.udel.cis.vsl.civl.model.IF.CIVLSource;
import edu.udel.cis.vsl.civl.model.IF.Scope;
import edu.udel.cis.vsl.civl.model.IF.expression.Expression;
import edu.udel.cis.vsl.civl.model.IF.expression.StructOrUnionLiteralExpression;
import edu.udel.cis.vsl.civl.model.IF.type.CIVLStructOrUnionType;
import edu.udel.cis.vsl.civl.model.IF.type.CIVLType;
import edu.udel.cis.vsl.civl.model.IF.variable.Variable;
import edu.udel.cis.vsl.sarl.IF.SymbolicUniverse;
import edu.udel.cis.vsl.sarl.IF.expr.SymbolicExpression;
import edu.udel.cis.vsl.sarl.IF.type.SymbolicTupleType;
public class CommonStructOrUnionLiteralExpression extends CommonExpression
implements StructOrUnionLiteralExpression {
private Expression[] fields;
public CommonStructOrUnionLiteralExpression(CIVLSource source,
Scope hscope, Scope lscope, CIVLType type, List<Expression> fields) {
super(source, hscope, lscope, type);
this.fields = new Expression[fields.size()];
fields.toArray(this.fields);
}
public CommonStructOrUnionLiteralExpression(CIVLSource source,
Scope hscope, Scope lscope, CIVLType type,
SymbolicExpression constantValue) {
super(source, hscope, lscope, type);
this.constantValue = constantValue;
}
@Override
public ExpressionKind expressionKind() {
return ExpressionKind.STRUCT_OR_UNION_LITERAL;
}
@Override
public Expression[] fields() {
return this.fields;
}
@Override
public void setFields(Expression[] fields) {
this.fields = fields;
}
@Override
public CIVLStructOrUnionType structOrUnionType() {
assert this.expressionType instanceof CIVLStructOrUnionType;
return (CIVLStructOrUnionType) this.expressionType;
}
@Override
public String toString() {
if (this.constantValue == null) {
String result = "{";
if (fields != null) {
CIVLStructOrUnionType structType = this.structOrUnionType();
String fieldName;
int i = 0;
for (Expression field : fields) {
fieldName = structType.getField(i).name().name();
i++;
result += " ." + fieldName + "=" + field + ", ";
}
result = result.substring(0, result.length() - 2);
}
result += " }";
return result;
} else
return this.constantValue.toString();
}
@Override
public Set<Variable> variableAddressedOf(Scope scope) {
Set<Variable> result = new HashSet<>();
if (fields != null) {
for (Expression field : fields) {
Set<Variable> elementResult = field.variableAddressedOf(scope);
if (elementResult != null)
result.addAll(elementResult);
}
}
return result;
}
@Override
public Set<Variable> variableAddressedOf() {
Set<Variable> result = new HashSet<>();
if (fields != null) {
for (Expression field : fields) {
Set<Variable> elementResult = field.variableAddressedOf();
if (elementResult != null)
result.addAll(elementResult);
}
}
return result;
}
@Override
public boolean isStruct() {
return this.structOrUnionType().isStructType();
}
@Override
public LiteralKind literalKind() {
return LiteralKind.STRUCT_OR_UNION;
}
@Override
public void calculateConstantValue(SymbolicUniverse universe) {
List<SymbolicExpression> fieldValues = new ArrayList<>();
for (Expression field : fields) {
SymbolicExpression fieldValue;
field.calculateConstantValue(universe);
fieldValue = field.constantValue();
if (fieldValue == null)
return;
fieldValues.add(fieldValue);
}
if (this.isStruct())
constantValue = universe.tuple(
(SymbolicTupleType) this.expressionType
.getDynamicType(universe), fieldValues);
}
@Override
public void setLiteralConstantValue(SymbolicExpression value) {
this.constantValue = value;
}
@Override
protected boolean expressionEquals(Expression expression) {
StructOrUnionLiteralExpression that = (StructOrUnionLiteralExpression) expression;
int thisFieldLength = this.fields.length;
if (thisFieldLength == that.fields().length) {
for (int i = 0; i < thisFieldLength; i++)
if (!this.fields[i].equals(that.fields()[i]))
return false;
return true;
}
return false;
}
@Override
public boolean containsHere() {
for (Expression field : fields) {
if (field.containsHere())
return true;
}
return false;
}
}