CommonArrayLiteralExpression.java
package dev.civl.mc.model.common.expression;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import dev.civl.mc.model.IF.CIVLSource;
import dev.civl.mc.model.IF.Scope;
import dev.civl.mc.model.IF.expression.ArrayLiteralExpression;
import dev.civl.mc.model.IF.expression.Expression;
import dev.civl.mc.model.IF.type.CIVLArrayType;
import dev.civl.mc.model.IF.type.CIVLPrimitiveType;
import dev.civl.mc.model.IF.type.CIVLType;
import dev.civl.mc.model.IF.variable.Variable;
import dev.civl.sarl.IF.SymbolicUniverse;
import dev.civl.sarl.IF.expr.SymbolicExpression;
import dev.civl.sarl.IF.type.SymbolicType;
public class CommonArrayLiteralExpression extends CommonExpression
implements
ArrayLiteralExpression {
/* ************************** Private Fields *************************** */
/**
* The elements of the array literal.
*/
private Expression[] elements;
/* **************************** Constructor **************************** */
/**
* Create a new instance of an array literal expression.
*
* @param source
* The source information corresponding to this array literal.
* @param scope
* The highest scope that this array literal accessed through its
* elements.
* @param arrayType
* The type of this array literal.
* @param elements
* The elements of this array literal.
*/
public CommonArrayLiteralExpression(CIVLSource source, Scope hscope,
Scope lscope, CIVLArrayType arrayType, List<Expression> elements) {
super(source, hscope, lscope, arrayType);
this.elements = new Expression[elements.size()];
elements.toArray(this.elements);
}
/* *************** Methods from ArrayLiteralExpression ***************** */
@Override
public Expression[] elements() {
return this.elements;
}
@Override
public void setElements(Expression[] elements) {
this.elements = elements;
}
@Override
public CIVLArrayType arrayType() {
assert this.expressionType instanceof CIVLArrayType;
return (CIVLArrayType) this.expressionType;
}
@Override
public CIVLType elementType() {
return this.arrayType().elementType();
}
/* ****************** Methods from LiteralExpression ******************* */
@Override
public LiteralKind literalKind() {
return LiteralKind.ARRAY;
}
/* ********************* Methods from Expression *********************** */
@Override
public ExpressionKind expressionKind() {
return ExpressionKind.ARRAY_LITERAL;
};
@Override
public Set<Variable> variableAddressedOf(Scope scope) {
Set<Variable> result = new HashSet<>();
if (elements != null) {
for (Expression element : elements) {
Set<Variable> elementResult = element
.variableAddressedOf(scope);
if (elementResult != null)
result.addAll(elementResult);
}
}
return result;
}
@Override
public Set<Variable> variableAddressedOf() {
Set<Variable> result = new HashSet<>();
if (elements != null) {
for (Expression element : elements) {
Set<Variable> elementResult = element.variableAddressedOf();
if (elementResult != null)
result.addAll(elementResult);
}
}
return result;
}
@Override
protected void addFreeVariables(Set<Variable> result) {
for (Expression element : elements)
((CommonExpression) element).addFreeVariables(result);
}
/* ************************ Methods from Object ************************ */
@Override
public String toString() {
StringBuffer result = new StringBuffer();
CIVLType eleType = this.arrayType().elementType();
boolean first;
if (eleType instanceof CIVLPrimitiveType) {
if (((CIVLPrimitiveType) eleType).isCharType()) {
result.append('\"');
for (Expression element : elements) {
result.append(element.toString());
}
result.append('\"');
return result.toString();
}
}
result.append("{");
first = true;
if (elements != null) {
for (Expression element : elements) {
if (first) {
result.append(element.toString());
first = false;
} else {
result.append(", ");
result.append(element.toString());
}
}
}
result.append("}");
return result.toString();
}
@Override
public void calculateConstantValueWork(SymbolicUniverse universe) {
List<SymbolicExpression> elementValues = new ArrayList<>();
SymbolicType elementType = this.elementType().getDynamicType(universe);
for (Expression element : elements) {
SymbolicExpression elementValue;
element.calculateConstantValue(universe);
elementValue = element.constantValue();
if (elementValue == null)
return;
elementValues.add(elementValue);
elementType = elementValue.type();
}
this.constantValue = universe.array(elementType, elementValues);
}
@Override
public void setLiteralConstantValue(SymbolicExpression value) {
this.constantValue = value;
}
@Override
protected boolean expressionEquals(Expression expression) {
ArrayLiteralExpression that = (ArrayLiteralExpression) expression;
int thisElementsLength = this.elements.length;
if (thisElementsLength == that.elements().length) {
for (int i = 0; i < thisElementsLength; i++)
if (!this.elements[i].equals(that.elements()[i]))
return false;
return true;
}
return false;
}
@Override
public boolean containsHere() {
for (Expression ele : elements) {
if (ele.containsHere())
return true;
}
return false;
}
}