package edu.ucsd.arcum.interpreter.ast.expressions;
import java.util.List;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import edu.ucsd.arcum.exceptions.SourceLocation;
import edu.ucsd.arcum.interpreter.ast.FormalParameter;
import edu.ucsd.arcum.interpreter.ast.ErrorMessage;
import edu.ucsd.arcum.interpreter.ast.TraitSignature;
import edu.ucsd.arcum.util.StringUtil;
public class UniversalQuantifier extends ConstraintExpression
{
private List<FormalParameter> boundVars;
private ConstraintExpression initialSet;
private ConstraintExpression body;
private ErrorMessage optionalMsg;
public UniversalQuantifier(SourceLocation location, List<FormalParameter> boundVars,
ConstraintExpression initialSet, ConstraintExpression body,
ErrorMessage optionalMsg)
{
super(location);
this.boundVars = boundVars;
this.initialSet = initialSet;
this.body = body;
this.optionalMsg = optionalMsg;
}
@Override protected void doCheckUserDefinedPredicates(List<TraitSignature> tupleSets,
Set<String> varsInScope)
{
Set nextScope = Sets.newHashSet(varsInScope);
nextScope.addAll(Lists.transform(boundVars, FormalParameter.getIdentifier));
initialSet.doCheckUserDefinedPredicates(tupleSets, nextScope);
body.doCheckUserDefinedPredicates(tupleSets, nextScope);
}
@Override public Set<String> getArcumVariableReferences() {
Set<String> result = Sets.newHashSet();
result.addAll(initialSet.getArcumVariableReferences());
Set<String> bodyVars = Sets.newHashSet(body.getArcumVariableReferences());
for (FormalParameter boundVar : boundVars) {
bodyVars.remove(boundVar.getIdentifier());
}
result.addAll(bodyVars);
return result;
}
@Override public String toString() {
StringBuilder buff = new StringBuilder();
buff.append("forall(");
StringUtil.separate(buff, boundVars, ", ");
buff.append(" : ");
buff.append(initialSet.toString());
buff.append(") {");
buff.append(body.toString());
buff.append(" }");
return buff.toString();
}
public List<FormalParameter> getBoundVars() {
return boundVars;
}
public ConstraintExpression getInitialSet() {
return initialSet;
}
public ConstraintExpression getBody() {
return body;
}
public boolean hasErrorMessage() {
return optionalMsg != ErrorMessage.EMPTY_MESSAGE;
}
// call only if hasErrorMessage returns true
public ErrorMessage getErrorMessage() {
return optionalMsg;
}
@Override public Set<String> findAllTraitDependencies() {
Set<String> result = body.findAllTraitDependencies();
result.removeAll(Lists.transform(boundVars, FormalParameter.getIdentifier));
result.addAll(initialSet.findAllTraitDependencies());
return result;
}
@Override public Set<String> findNonMonotonicDependencies() {
return this.findAllTraitDependencies();
}
}