CommonRecDomainLiteralExpression.java
package dev.civl.mc.model.common.expression;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
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.Expression;
import dev.civl.mc.model.IF.expression.RecDomainLiteralExpression;
import dev.civl.mc.model.IF.type.CIVLDomainType;
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.SymbolicTupleType;
public class CommonRecDomainLiteralExpression extends CommonExpression
implements
RecDomainLiteralExpression {
private Expression[] ranges;
public CommonRecDomainLiteralExpression(CIVLSource source, Scope lscope,
List<Expression> ranges, CIVLType type) {
super(source, null, lscope, type);
this.ranges = new Expression[ranges.size()];
ranges.toArray(this.ranges);
}
@Override
public LiteralKind literalKind() {
return LiteralKind.DOMAIN;
}
@Override
public ExpressionKind expressionKind() {
return ExpressionKind.REC_DOMAIN_LITERAL;
}
@Override
public Set<Variable> variableAddressedOf(Scope scope) {
Set<Variable> result = new HashSet<>();
if (this.ranges != null) {
for (Expression range : ranges) {
Set<Variable> rangeResult = range.variableAddressedOf(scope);
if (rangeResult != null)
result.addAll(rangeResult);
}
}
return result;
}
@Override
public Set<Variable> variableAddressedOf() {
Set<Variable> result = new HashSet<>();
if (this.ranges != null) {
for (Expression range : ranges) {
Set<Variable> rangeResult = range.variableAddressedOf();
if (rangeResult != null)
result.addAll(rangeResult);
}
}
return result;
}
@Override
public Expression rangeAt(int index) {
return ranges[index];
}
@Override
public int dimension() {
return ranges.length;
}
@Override
public String toString() {
StringBuffer string = new StringBuffer();
int dim = this.dimension();
boolean first = true;
string.append("{");
for (int i = 0; i < dim; i++) {
if (first)
first = false;
else
string.append(", ");
string.append(ranges[i]);
}
string.append("}");
return string.toString();
}
@Override
public void calculateConstantValueWork(SymbolicUniverse universe) {
List<SymbolicExpression> rangeValues = new ArrayList<>();
List<SymbolicExpression> domValueComponents = new LinkedList<>();
SymbolicExpression rangesArray;
CIVLDomainType civlDomType = (CIVLDomainType) this.expressionType;
for (Expression range : ranges) {
SymbolicExpression rangeValue;
range.calculateConstantValue(universe);
rangeValue = range.constantValue();
if (rangeValue == null)
return;
rangeValues.add(rangeValue);
}
// Adding components
domValueComponents.add(universe.integer(this.dimension()));
// Union field index which indicates it's a rectangular domain.
domValueComponents.add(universe.zeroInt());
rangesArray = universe.array(rangeValues.get(0).type(), rangeValues);
domValueComponents.add(universe.unionInject(
civlDomType.getDynamicSubTypesUnion(universe),
universe.intObject(0), rangesArray));
// The cast is guaranteed
this.constantValue = universe.tuple(
(SymbolicTupleType) civlDomType.getDynamicType(universe),
domValueComponents);
}
@Override
public void setLiteralConstantValue(SymbolicExpression value) {
this.constantValue = value;
}
@Override
protected boolean expressionEquals(Expression expression) {
RecDomainLiteralExpression that = (RecDomainLiteralExpression) expression;
int thisDim = this.dimension();
if (thisDim == that.dimension()) {
for (int i = 0; i < thisDim; i++)
if (!this.rangeAt(i).equals(that.rangeAt(i)))
return false;
return true;
}
return false;
}
@Override
protected void addFreeVariables(Set<Variable> result) {
for (Expression range : ranges)
((CommonExpression) range).addFreeVariables(result);
}
}