Search in sources :

Example 11 with PrimSig

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);
}
Also used : ErrorType(edu.mit.csail.sdg.alloy4.ErrorType) ProductType(edu.mit.csail.sdg.ast.Type.ProductType) ProductType(edu.mit.csail.sdg.ast.Type.ProductType) ErrorWarning(edu.mit.csail.sdg.alloy4.ErrorWarning) ArrayList(java.util.ArrayList) List(java.util.List) JoinableList(edu.mit.csail.sdg.alloy4.JoinableList) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 12 with PrimSig

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);
    }
}
Also used : A4Tuple(edu.mit.csail.sdg.translator.A4Tuple) Expr(edu.mit.csail.sdg.ast.Expr) A4TupleSet(edu.mit.csail.sdg.translator.A4TupleSet) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 13 with PrimSig

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)));
    }
}
Also used : PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) Sig(edu.mit.csail.sdg.ast.Sig) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 14 with PrimSig

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);
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ArrayList(java.util.ArrayList) A4TupleSet(edu.mit.csail.sdg.translator.A4TupleSet) A4Tuple(edu.mit.csail.sdg.translator.A4Tuple) ErrorFatal(edu.mit.csail.sdg.alloy4.ErrorFatal) Expr(edu.mit.csail.sdg.ast.Expr) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 15 with PrimSig

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;
}
Also used : ErrorFatal(edu.mit.csail.sdg.alloy4.ErrorFatal) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Aggregations

PrimSig (edu.mit.csail.sdg.ast.Sig.PrimSig)34 Sig (edu.mit.csail.sdg.ast.Sig)14 Expr (edu.mit.csail.sdg.ast.Expr)10 SubsetSig (edu.mit.csail.sdg.ast.Sig.SubsetSig)9 ArrayList (java.util.ArrayList)8 Field (edu.mit.csail.sdg.ast.Sig.Field)6 ErrorFatal (edu.mit.csail.sdg.alloy4.ErrorFatal)5 HashMap (java.util.HashMap)5 TupleSet (kodkod.instance.TupleSet)5 ConstList (edu.mit.csail.sdg.alloy4.ConstList)4 ErrorSyntax (edu.mit.csail.sdg.alloy4.ErrorSyntax)4 LinkedHashMap (java.util.LinkedHashMap)4 List (java.util.List)4 Map (java.util.Map)4 Err (edu.mit.csail.sdg.alloy4.Err)3 ErrorType (edu.mit.csail.sdg.alloy4.ErrorType)3 Pos (edu.mit.csail.sdg.alloy4.Pos)3 SafeList (edu.mit.csail.sdg.alloy4.SafeList)3 ExprVar (edu.mit.csail.sdg.ast.ExprVar)3 A4Tuple (edu.mit.csail.sdg.translator.A4Tuple)3