use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class ExprBinary method resolve.
// ============================================================================================================//
/**
* {@inheritDoc}
*/
@Override
public Expr resolve(Type p, Collection<ErrorWarning> warns) {
if (errors.size() > 0)
return this;
ErrorWarning w = null;
Type a = left.type, b = right.type;
switch(op) {
case MUL:
case DIV:
case REM:
case LT:
case LTE:
case GT:
case GTE:
case SHL:
case SHR:
case SHA:
case NOT_LTE:
case NOT_GTE:
case NOT_LT:
case NOT_GT:
{
a = (b = Type.smallIntType());
break;
}
case AND:
case OR:
case IFF:
case IMPLIES:
{
a = (b = Type.FORMULA);
break;
}
case EQUALS:
case NOT_EQUALS:
{
p = a.intersect(b);
if (p.hasTuple()) {
a = p;
b = p;
} else {
a = a.pickCommonArity(b);
b = b.pickCommonArity(a);
}
// } else
if (warns == null) {
break;
} else if (left.type.hasTuple() && right.type.hasTuple() && !(left.type.intersects(right.type))) {
w = warn("== is redundant, because the left and right expressions are always disjoint.");
} else if (left.isSame(right)) {
w = warn("== is redundant, because the left and right expressions always have the same value.");
}
break;
}
case IN:
case NOT_IN:
{
a = a.pickCommonArity(b);
b = b.intersect(a);
if (warns == null)
break;
if (left.type.hasNoTuple() && right.type.hasNoTuple())
w = warn("Subset operator is redundant, because both subexpressions are always empty.");
else if (left.type.hasNoTuple())
w = warn("Subset operator is redundant, because the left subexpression is always empty.");
else if (right.type.hasNoTuple())
w = warn("Subset operator is redundant, because the right subexpression is always empty.");
else if (b.hasNoTuple())
w = warn("Subset operator is redundant, because the left and right subexpressions are always disjoint.");
else if (left.isSame(right))
w = warn("Subset operator is redundant, because the left and right expressions always have the same value.");
break;
}
case INTERSECT:
{
a = a.intersect(p);
b = b.intersect(p);
if (warns != null && type.hasNoTuple())
w = warn("& is irrelevant because the two subexpressions are always disjoint.");
break;
}
case IPLUS:
case IMINUS:
{
a = Type.smallIntType();
b = Type.smallIntType();
break;
}
case PLUSPLUS:
case PLUS:
{
a = a.intersect(p);
b = b.intersect(p);
// b=Type.makeInt(b); }
if (warns == null)
break;
if (a == EMPTY && b == EMPTY)
w = warn(this + " is irrelevant since both subexpressions are redundant.", p);
else if (a == EMPTY)
w = warn(this + " is irrelevant since the left subexpression is redundant.", p);
else if (b == EMPTY || (op == Op.PLUSPLUS && !right.type.canOverride(left.type)))
w = warn(this + " is irrelevant since the right subexpression is redundant.", p);
break;
}
case MINUS:
{
a = p;
b = p.intersect(b);
// } else
if (warns != null && (type.hasNoTuple() || b.hasNoTuple())) {
w = warn("- is irrelevant since the right expression is redundant.", p);
}
break;
}
case JOIN:
{
if (warns != null && type.hasNoTuple())
w = warn("The join operation here always yields an empty set.");
a = (b = EMPTY);
for (ProductType aa : left.type) for (ProductType bb : right.type) if (p.hasArity(aa.arity() + bb.arity() - 2)) {
PrimSig j = aa.get(aa.arity() - 1).intersect(bb.get(0));
if (j != Sig.NONE)
for (ProductType cc : p.intersect(aa.join(bb))) if (!cc.isEmpty()) {
List<PrimSig> v = new ArrayList<PrimSig>(cc.arity() + 1);
for (int i = 0; i < cc.arity(); i++) v.add(cc.get(i));
v.add(aa.arity() - 1, j);
a = a.merge(Type.make(v, 0, aa.arity()));
b = b.merge(Type.make(v, aa.arity() - 1, v.size()));
}
}
if (a == EMPTY || b == EMPTY) {
// Continue the best we can; we
// should have issued a
// relevance warning elsewhere
// already.
a = (b = EMPTY);
for (ProductType aa : left.type) for (ProductType bb : right.type) if (p.hasArity(aa.arity() + bb.arity() - 2) && aa.get(aa.arity() - 1).intersects(bb.get(0))) {
a = a.merge(aa);
b = b.merge(bb);
}
}
if (a == EMPTY || b == EMPTY) {
// Continue the best we can; we
// should have issued a
// relevance warning elsewhere
// already.
a = (b = EMPTY);
for (ProductType aa : left.type) for (ProductType bb : right.type) if (p.hasArity(aa.arity() + bb.arity() - 2)) {
a = a.merge(aa);
b = b.merge(bb);
}
}
break;
}
case DOMAIN:
{
// leftType such that r1<:r2 in parentType}
if (warns != null && type.hasNoTuple())
w = warn("<: is irrelevant because the result is always empty.");
Type leftType = EMPTY, rightType = EMPTY;
for (ProductType aa : a) if (aa.arity() == 1)
for (ProductType bb : b) if (p.hasArity(bb.arity()))
for (ProductType cc : p.intersect(bb.columnRestrict(aa.get(0), 0))) if (!cc.isEmpty()) {
leftType = leftType.merge(cc, 0, 1);
rightType = rightType.merge(cc);
}
if (leftType == EMPTY || rightType == EMPTY) {
// We try to
// proceed the
// best we can
leftType = a.extract(1);
rightType = b.pickCommonArity(p);
}
a = leftType;
b = rightType;
break;
}
case RANGE:
{
// leftType such that r1:>r2 in parentType}
if (warns != null && type.hasNoTuple())
w = warn(":> is irrelevant because the result is always empty.");
Type leftType = EMPTY, rightType = EMPTY;
for (ProductType bb : b) if (bb.arity() == 1)
for (ProductType aa : a) if (p.hasArity(aa.arity()))
for (ProductType cc : p.intersect(aa.columnRestrict(bb.get(0), aa.arity() - 1))) if (!cc.isEmpty()) {
leftType = leftType.merge(cc);
rightType = rightType.merge(cc, cc.arity() - 1, cc.arity());
}
if (leftType == EMPTY || rightType == EMPTY) {
// We try to
// proceed the
// best we can
leftType = a.pickCommonArity(p);
rightType = b.extract(1);
}
a = leftType;
b = rightType;
break;
}
default:
{
// leftType such that r1->r2 in parentType}
if (warns == null) {
// do nothing
} else if (a.hasTuple()) {
if (b.hasNoTuple())
w = warn("The left expression of -> is irrelevant because the right expression is always empty.");
} else {
if (b.hasTuple())
w = warn("The right expression of -> is irrelevant because the left expression is always empty.");
}
Type leftType = EMPTY, rightType = EMPTY;
for (ProductType aa : a) if (!aa.isEmpty())
for (ProductType bb : b) if (!bb.isEmpty() && p.hasArity(aa.arity() + bb.arity()))
for (ProductType cc : p.intersect(aa.product(bb))) if (!cc.isEmpty()) {
leftType = leftType.merge(cc, 0, aa.arity());
rightType = rightType.merge(cc, aa.arity(), cc.arity());
}
// relevance warning already.
if (leftType == EMPTY || rightType == EMPTY) {
leftType = a;
rightType = b;
}
a = leftType;
b = rightType;
}
}
Expr left = this.left.resolve(a, warns);
Expr right = this.right.resolve(b, warns);
if (w != null)
warns.add(w);
return (left == this.left && right == this.right) ? this : op.make(pos, closingBracket, left, right);
}
use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class StaticInstanceReader method atoms.
/**
* Constructs the atoms corresponding to the given sig.
*/
private void atoms(A4Solution sol, PrimSig s) throws Err {
Expr sum = Sig.NONE;
for (PrimSig c : s.children()) {
sum = sum.plus(c);
atoms(sol, c);
}
// This ensures
A4TupleSet ts = (A4TupleSet) (sol.eval(s.minus(sum)));
// specific sig
for (A4Tuple z : ts) {
String atom = z.atom(0);
int i, dollar = atom.lastIndexOf('$');
try {
i = Integer.parseInt(dollar >= 0 ? atom.substring(dollar + 1) : atom);
} catch (NumberFormatException ex) {
i = Integer.MAX_VALUE;
}
AlloyAtom at = new AlloyAtom(sig(s), ts.size() == 1 ? Integer.MAX_VALUE : i, atom);
atom2sets.put(at, new LinkedHashSet<AlloySet>());
string2atom.put(atom, at);
}
}
use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class StaticInstanceReader method sigMETA.
/**
* Returns the AlloyType corresponding to the given sig; create an AlloyType for
* it if none existed before.
*/
private void sigMETA(SubsetSig s) throws Err {
AlloyAtom atom;
AlloyType type = sig2type.get(s);
if (type != null)
return;
type = makeType(s.label, s.isOne != null, s.isAbstract != null, false, s.isPrivate != null, s.isMeta != null, s.isEnum != null);
atom = new AlloyAtom(type, Integer.MAX_VALUE, s.label);
atom2sets.put(atom, new LinkedHashSet<AlloySet>());
sig2atom.put(s, atom);
sig2type.put(s, type);
ts.put(type, AlloyType.SET);
for (Sig p : s.parents) {
if (p instanceof SubsetSig)
sigMETA((SubsetSig) p);
else
sigMETA((PrimSig) p);
ins.add(new AlloyTuple(atom, sig2atom.get(p)));
}
}
use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class StaticInstanceReader method setOrRel.
/**
* Construct an AlloySet or AlloyRelation corresponding to the given expression.
*/
private void setOrRel(A4Solution sol, String label, Expr expr, boolean isPrivate, boolean isMeta) throws Err {
for (List<PrimSig> ps : expr.type().fold()) {
if (ps.size() == 1) {
PrimSig t = ps.get(0);
AlloySet set = makeSet(label, isPrivate, isMeta, sig(t));
sets.add(set);
for (A4Tuple tp : (A4TupleSet) (sol.eval(expr.intersect(t)))) {
atom2sets.get(string2atom.get(tp.atom(0))).add(set);
}
} else {
Expr mask = null;
List<AlloyType> types = new ArrayList<AlloyType>(ps.size());
for (int i = 0; i < ps.size(); i++) {
types.add(sig(ps.get(i)));
if (mask == null)
mask = ps.get(i);
else
mask = mask.product(ps.get(i));
}
AlloyRelation rel = makeRel(label, isPrivate, isMeta, types);
Set<AlloyTuple> ts = new LinkedHashSet<AlloyTuple>();
for (A4Tuple tp : (A4TupleSet) (sol.eval(expr.intersect(mask)))) {
AlloyAtom[] atoms = new AlloyAtom[tp.arity()];
for (int i = 0; i < tp.arity(); i++) {
atoms[i] = string2atom.get(tp.atom(i));
if (atoms[i] == null)
throw new ErrorFatal("Unexpected XML inconsistency: cannot resolve atom " + tp.atom(i));
}
ts.add(new AlloyTuple(atoms));
}
rels.put(rel, ts);
}
}
}
use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class StaticInstanceReader method sigMETA.
/**
* Returns the AlloyType corresponding to the given sig; create an AlloyType for
* it if none existed before.
*/
private AlloyType sigMETA(PrimSig s) throws Err {
if (s == Sig.NONE)
throw new ErrorFatal("Unexpected sig \"none\" encountered.");
AlloyType type = sig2type.get(s);
if (type != null)
return type;
if (s == Sig.UNIV)
type = AlloyType.UNIV;
else if (s == Sig.SIGINT)
type = AlloyType.INT;
else if (s == Sig.SEQIDX)
type = AlloyType.SEQINT;
else if (s == Sig.STRING)
type = AlloyType.STRING;
else
type = makeType(s.label, s.isOne != null, s.isAbstract != null, false, s.isPrivate != null, s.isMeta != null, s.isEnum != null);
sig2type.put(s, type);
AlloyAtom atom = new AlloyAtom(type, (type == AlloyType.SEQINT ? Integer.MIN_VALUE : Integer.MAX_VALUE), s.label);
atom2sets.put(atom, new LinkedHashSet<AlloySet>());
sig2atom.put(s, atom);
if (s.parent != Sig.UNIV && s.parent != null)
ts.put(type, sigMETA(s.parent));
if (s.parent != null)
exts.add(new AlloyTuple(atom, sig2atom.get(s.parent)));
Iterable<PrimSig> children = (s == Sig.UNIV ? toplevels : s.children());
for (PrimSig sub : children) sigMETA(sub);
return type;
}
Aggregations