Search in sources :

Example 1 with PrimSig

use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.

the class CompModule method resolveSig.

/**
 * The given Sig will now point to a nonnull Sig.
 */
private static Sig resolveSig(CompModule res, Set<Object> topo, Sig oldS) throws Err {
    if (res.new2old.containsKey(oldS))
        return oldS;
    Sig realSig;
    final Pos pos = oldS.pos;
    final CompModule u = res.sig2module.get(oldS);
    final String name = base(oldS);
    final String fullname = (u.path.length() == 0) ? ("this/" + name) : (u.path + "/" + name);
    if (!topo.add(oldS))
        throw new ErrorType(pos, "Sig " + oldS + " is involved in a cyclic inheritance.");
    if (oldS instanceof SubsetSig) {
        List<Sig> parents = new ArrayList<Sig>();
        for (Sig n : ((SubsetSig) oldS).parents) {
            Sig parentAST = u.getRawSIG(n.pos, n.label);
            if (parentAST == null)
                throw new ErrorSyntax(n.pos, "The sig \"" + n.label + "\" cannot be found.");
            parents.add(resolveSig(res, topo, parentAST));
        }
        realSig = new SubsetSig(fullname, parents, oldS.attributes.toArray(new Attr[0]));
    } else {
        Sig sup = ((PrimSig) oldS).parent;
        Sig parentAST = u.getRawSIG(sup.pos, sup.label);
        if (parentAST == null)
            throw new ErrorSyntax(sup.pos, "The sig \"" + sup.label + "\" cannot be found.");
        Sig parent = resolveSig(res, topo, parentAST);
        if (!(parent instanceof PrimSig))
            throw new ErrorSyntax(sup.pos, "Cannot extend the subset signature \"" + parent + "\".\n" + "A signature can only extend a toplevel signature or a subsignature.");
        PrimSig p = (PrimSig) parent;
        realSig = new PrimSig(fullname, p, oldS.attributes.toArray(new Attr[0]));
    }
    res.new2old.put(realSig, oldS);
    res.sig2module.put(realSig, u);
    for (CompModule m : res.allModules) {
        for (Map.Entry<String, Sig> e : m.sigs.entrySet()) if (e.getValue() == oldS)
            e.setValue(realSig);
        for (Map.Entry<String, Sig> e : m.params.entrySet()) if (e.getValue() == oldS)
            e.setValue(realSig);
    }
    if (res.exactSigs.remove(oldS))
        res.exactSigs.add(realSig);
    return realSig;
}
Also used : PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Sig(edu.mit.csail.sdg.ast.Sig) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) ErrorSyntax(edu.mit.csail.sdg.alloy4.ErrorSyntax) ErrorType(edu.mit.csail.sdg.alloy4.ErrorType) Pos(edu.mit.csail.sdg.alloy4.Pos) ArrayList(java.util.ArrayList) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 2 with PrimSig

use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.

the class SimInstance method isIn.

/**
 * Helper method that evaluates the formula "a in b" where b.mult==0
 */
public boolean isIn(SimTuple a, Expr b) throws Err {
    b = b.deNOP();
    if (b instanceof PrimSig && ((PrimSig) b).builtin) {
        if (a.arity() != 1)
            return false;
        if (b.isSame(Sig.UNIV))
            return true;
        if (b.isSame(Sig.NONE))
            return false;
        if (b.isSame(Sig.SEQIDX)) {
            Integer i = a.get(0).toInt(null);
            return i != null && i >= 0 && i < maxseq;
        }
        if (b.isSame(Sig.SIGINT)) {
            Integer i = a.get(0).toInt(null);
            return i != null;
        }
        if (b.isSame(Sig.STRING)) {
            String at = a.get(0).toString();
            return at.length() > 0 && (at.charAt(0) == '\"');
        }
    }
    if (b instanceof ExprBinary && ((ExprBinary) b).op == ExprBinary.Op.ARROW) {
        Expr left = ((ExprBinary) b).left, right = ((ExprBinary) b).right;
        int ll = left.type().arity(), rr = right.type().arity();
        if (ll <= rr)
            return isIn(a.head(ll), left) && isIn(a.tail(rr), right);
        return isIn(a.tail(rr), right) && isIn(a.head(ll), left);
    }
    if (b instanceof ExprBinary && ((ExprBinary) b).op == ExprBinary.Op.PLUS) {
        return isIn(a, ((ExprBinary) b).left) || isIn(a, ((ExprBinary) b).right);
    }
    if (b instanceof ExprBinary && ((ExprBinary) b).op == ExprBinary.Op.MINUS) {
        return isIn(a, ((ExprBinary) b).left) && !isIn(a, ((ExprBinary) b).right);
    }
    return cset(b).has(a);
}
Also used : ExprBinary(edu.mit.csail.sdg.ast.ExprBinary) Expr(edu.mit.csail.sdg.ast.Expr) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 3 with PrimSig

use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.

the class SimInstance method makeAtom.

/**
 * Create a fresh atom for the given sig, then return the newly created atom.
 *
 * @throws ErrorAPI if attempting to add an atom to an abstract sig with
 *             children, or a builtin sig, or a subset sig.
 */
public SimAtom makeAtom(Sig sig) throws Err {
    if (sig.builtin)
        throw new ErrorAPI("Cannot add an atom to a builtin sig.");
    if (!(sig instanceof PrimSig))
        throw new ErrorAPI("Cannot add an atom to a subset sig.");
    PrimSig s = (PrimSig) sig;
    if (s.isAbstract != null && !s.children().isEmpty())
        throw new ErrorAPI("Cannot add an atom to an abstract parent sig.");
    String label = sig.label + "$";
    if (label.startsWith("this/"))
        label = label.substring(5);
    for (int i = 0; ; i++) {
        SimAtom atom = SimAtom.make(label + i);
        if (hasAtom(atom))
            continue;
        SimTupleset add = SimTupleset.make(SimTuple.make(atom));
        if (cacheUNIV != null)
            cacheUNIV = cacheUNIV.union(add);
        for (; s != null; s = s.parent) if (!s.builtin) {
            SimTupleset old = sfs.get(s);
            if (old == null || old.empty())
                sfs.put(s, add);
            else if (!add.in(old))
                sfs.put(s, old.union(add));
            else
                break;
        }
        return atom;
    }
}
Also used : ErrorAPI(edu.mit.csail.sdg.alloy4.ErrorAPI) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig)

Example 4 with PrimSig

use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.

the class SimInstance method validate.

/**
 * Checks whether this instance satisfies every fact defined in the given model.
 *
 * @param world - this must be the root of the Alloy model
 * @return an empty String if yes, nonempty String if no
 */
public String validate(Module world) {
    try {
        for (Sig s : world.getAllReachableSigs()) if (!s.builtin) {
            if (s.isLone != null && !(visit(s).longsize() <= 1))
                return "There can be at most one " + s;
            if (s.isOne != null && !(visit(s).longsize() == 1))
                return "There must be exactly one " + s;
            if (s.isSome != null && !(visit(s).longsize() >= 1))
                return "There must be at least one " + s;
            if (s instanceof SubsetSig) {
                SubsetSig p = (SubsetSig) s;
                Expr sum = null;
                for (Sig par : p.parents) sum = par.plus(sum);
                if (p.exact) {
                    if (!equal(s, sum))
                        return "Sig " + s + " must be equal to the union of its parents " + p.parents;
                } else {
                    if (!isIn(s, sum))
                        return "Sig " + s + " must be equal or subset of its parents " + p.parents;
                }
            } else if (s != Sig.UNIV && s != Sig.NONE) {
                PrimSig p = (PrimSig) s;
                if (!isIn(s, p.parent))
                    return "Sig " + s + " must be equal or subset of its parent " + p.parent;
            }
            if (s.isAbstract != null) {
                Expr sum = null;
                for (Sig x : ((PrimSig) s).children()) sum = x.plus(sum);
                if (sum != null && !equal(s, sum))
                    return "Abstract sig " + s + " must be equal to the union of its subsigs";
            }
            for (Decl d : s.getFieldDecls()) for (ExprHasName f : d.names) if (!((Field) f).defined) {
                if (!cform(s.decl.get().join(f).in(d.expr).forAll(s.decl))) {
                    return "Field " + f + " violated its bound: " + visit((Field) f) + "\n" + d.expr;
                }
                SimTupleset setS = visit(s);
                SimTupleset setF = visit((Field) f);
                for (SimAtom x : setF.getAllAtoms(0)) if (!setS.has(x))
                    return "Field " + f + " first column has extra atom: " + setF + " not in " + setS;
            }
            for (Decl d : s.getFieldDecls()) {
                if (d.disjoint != null && d.names.size() > 0) {
                    if (!cform(ExprList.makeDISJOINT(null, null, d.names)))
                        return "Fields must be disjoint.";
                }
                if (d.disjoint2 != null)
                    for (ExprHasName f : d.names) {
                        Decl that = s.oneOf("that");
                        Expr formula = s.decl.get().equal(that.get()).not().implies(s.decl.get().join(f).intersect(that.get().join(f)).no());
                        if (!cform(formula.forAll(that).forAll(s.decl)))
                            return "Fields must be disjoint.";
                    }
            }
            for (Expr f : s.getFacts()) {
                if (!cform(f.forAll(s.decl))) {
                    f = f.deNOP();
                    if (f instanceof ExprUnary) {
                        ExprUnary u = (ExprUnary) f;
                        f = u.sub.deNOP();
                        if (f instanceof ExprBinary) {
                            ExprBinary b = (ExprBinary) f;
                            if (b.op == ExprBinary.Op.JOIN && b.left.isSame(s.decl.get()) && b.right.deNOP() instanceof Field) {
                                String n = ((Field) (b.right.deNOP())).label;
                                if (u.op == ExprUnary.Op.SOME)
                                    return "The " + n + " cannot be empty.";
                                if (u.op == ExprUnary.Op.LONE)
                                    return "The " + n + " cannot have more than one value.";
                                if (u.op == ExprUnary.Op.ONE)
                                    return "The " + n + " must have exactly one value.";
                                if (u.op == ExprUnary.Op.NO)
                                    return "The " + n + " must be empty.";
                            }
                        }
                    }
                    return "Cannot violate a consistency constraint";
                }
            }
        }
        for (Module m : world.getAllReachableModules()) for (Pair<String, Expr> f : m.getAllFacts()) if (!cform(f.b)) {
            String err = f.a;
            if (err.matches("^fact\\$[0-9][0-9]*"))
                err = f.b.toString();
            if (err.length() >= 2 && err.startsWith("\"") && err.endsWith("\""))
                err = err.substring(1, err.length() - 1);
            return "Violation: " + err;
        }
        return "";
    } catch (Err ex) {
        return "An internal error has occured:\n" + ex.dump();
    }
}
Also used : Err(edu.mit.csail.sdg.alloy4.Err) Decl(edu.mit.csail.sdg.ast.Decl) 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) Field(edu.mit.csail.sdg.ast.Sig.Field) ExprBinary(edu.mit.csail.sdg.ast.ExprBinary) Expr(edu.mit.csail.sdg.ast.Expr) ExprHasName(edu.mit.csail.sdg.ast.ExprHasName) ExprUnary(edu.mit.csail.sdg.ast.ExprUnary) Module(edu.mit.csail.sdg.ast.Module) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Pair(edu.mit.csail.sdg.alloy4.Pair)

Example 5 with PrimSig

use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.

the class A4Solution method rename.

/**
 * Helper method that chooses a name for each atom based on its most specific
 * sig; (external caller should call this method with s==null and nexts==null)
 */
private static void rename(A4Solution frame, PrimSig s, Map<Sig, List<Tuple>> nexts, UniqueNameGenerator un) throws Err {
    if (s == null) {
        for (ExprVar sk : frame.skolems) un.seen(sk.label);
        // Store up the skolems
        List<Object> skolems = new ArrayList<Object>();
        for (Map.Entry<Relation, Type> e : frame.rel2type.entrySet()) {
            Relation r = e.getKey();
            if (!frame.eval.instance().contains(r))
                continue;
            Type t = e.getValue();
            if (t.arity() > r.arity())
                // Something is wrong; let's skip it
                continue;
            while (t.arity() < r.arity()) t = UNIV.type().product(t);
            String n = Util.tail(r.name());
            while (n.length() > 0 && n.charAt(0) == '$') n = n.substring(1);
            skolems.add(n);
            skolems.add(t);
            skolems.add(r);
        }
        // Find all suitable "next" or "prev" relations
        nexts = new LinkedHashMap<Sig, List<Tuple>>();
        for (Sig sig : frame.sigs) for (Field f : sig.getFields()) if (f.label.compareToIgnoreCase("next") == 0) {
            List<List<PrimSig>> fold = f.type().fold();
            if (fold.size() == 1) {
                List<PrimSig> t = fold.get(0);
                if (t.size() == 3 && t.get(0).isOne != null && t.get(1) == t.get(2) && !nexts.containsKey(t.get(1))) {
                    TupleSet set = frame.eval.evaluate(frame.a2k(t.get(1)));
                    if (set.size() <= 1)
                        continue;
                    TupleSet next = frame.eval.evaluate(frame.a2k(t.get(0)).join(frame.a2k(f)));
                    List<Tuple> test = isOrder(next, set);
                    if (test != null)
                        nexts.put(t.get(1), test);
                } else if (t.size() == 2 && t.get(0) == t.get(1) && !nexts.containsKey(t.get(0))) {
                    TupleSet set = frame.eval.evaluate(frame.a2k(t.get(0)));
                    if (set.size() <= 1)
                        continue;
                    TupleSet next = frame.eval.evaluate(frame.a2k(f));
                    List<Tuple> test = isOrder(next, set);
                    if (test != null)
                        nexts.put(t.get(1), test);
                }
            }
        }
        for (Sig sig : frame.sigs) for (Field f : sig.getFields()) if (f.label.compareToIgnoreCase("prev") == 0) {
            List<List<PrimSig>> fold = f.type().fold();
            if (fold.size() == 1) {
                List<PrimSig> t = fold.get(0);
                if (t.size() == 3 && t.get(0).isOne != null && t.get(1) == t.get(2) && !nexts.containsKey(t.get(1))) {
                    TupleSet set = frame.eval.evaluate(frame.a2k(t.get(1)));
                    if (set.size() <= 1)
                        continue;
                    TupleSet next = frame.eval.evaluate(frame.a2k(t.get(0)).join(frame.a2k(f)).transpose());
                    List<Tuple> test = isOrder(next, set);
                    if (test != null)
                        nexts.put(t.get(1), test);
                } else if (t.size() == 2 && t.get(0) == t.get(1) && !nexts.containsKey(t.get(0))) {
                    TupleSet set = frame.eval.evaluate(frame.a2k(t.get(0)));
                    if (set.size() <= 1)
                        continue;
                    TupleSet next = frame.eval.evaluate(frame.a2k(f).transpose());
                    List<Tuple> test = isOrder(next, set);
                    if (test != null)
                        nexts.put(t.get(1), test);
                }
            }
        }
        // Assign atom->name and atom->MostSignificantSig
        for (Tuple t : frame.eval.evaluate(Expression.INTS)) {
            frame.atom2sig.put(t.atom(0), SIGINT);
        }
        for (Tuple t : frame.eval.evaluate(KK_SEQIDX)) {
            frame.atom2sig.put(t.atom(0), SEQIDX);
        }
        for (Tuple t : frame.eval.evaluate(KK_STRING)) {
            frame.atom2sig.put(t.atom(0), STRING);
        }
        for (Sig sig : frame.sigs) if (sig instanceof PrimSig && !sig.builtin && ((PrimSig) sig).isTopLevel())
            rename(frame, (PrimSig) sig, nexts, un);
        // These are redundant atoms that were not chosen to be in the final
        // instance
        int unused = 0;
        for (Tuple tuple : frame.eval.evaluate(Expression.UNIV)) {
            Object atom = tuple.atom(0);
            if (!frame.atom2sig.containsKey(atom)) {
                frame.atom2name.put(atom, "unused" + unused);
                unused++;
            }
        }
        // Add the skolems
        for (int num = skolems.size(), i = 0; i < num - 2; i = i + 3) {
            String n = (String) skolems.get(i);
            while (n.length() > 0 && n.charAt(0) == '$') n = n.substring(1);
            Type t = (Type) skolems.get(i + 1);
            Relation r = (Relation) skolems.get(i + 2);
            frame.addSkolem(un.make("$" + n), t, r);
        }
        return;
    }
    for (PrimSig c : s.children()) rename(frame, c, nexts, un);
    String signame = un.make(s.label.startsWith("this/") ? s.label.substring(5) : s.label);
    List<Tuple> list = new ArrayList<Tuple>();
    for (Tuple t : frame.eval.evaluate(frame.a2k(s))) list.add(t);
    List<Tuple> order = nexts.get(s);
    if (order != null && order.size() == list.size() && order.containsAll(list)) {
        list = order;
    }
    int i = 0;
    for (Tuple t : list) {
        if (frame.atom2sig.containsKey(t.atom(0)))
            // This means one of the subsig has already claimed
            continue;
        // this atom.
        String x = signame + "$" + i;
        i++;
        frame.atom2sig.put(t.atom(0), s);
        frame.atom2name.put(t.atom(0), x);
        ExprVar v = ExprVar.make(null, x, s.type());
        TupleSet ts = t.universe().factory().range(t, t);
        Relation r = Relation.unary(x);
        frame.eval.instance().add(r, ts);
        frame.a2k.put(v, r);
        frame.atoms.add(v);
    }
}
Also used : ExprVar(edu.mit.csail.sdg.ast.ExprVar) TupleSet(kodkod.instance.TupleSet) ArrayList(java.util.ArrayList) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Sig(edu.mit.csail.sdg.ast.Sig) Field(edu.mit.csail.sdg.ast.Sig.Field) Relation(kodkod.ast.Relation) Type(edu.mit.csail.sdg.ast.Type) SafeList(edu.mit.csail.sdg.alloy4.SafeList) List(java.util.List) ArrayList(java.util.ArrayList) ConstList(edu.mit.csail.sdg.alloy4.ConstList) ConstMap(edu.mit.csail.sdg.alloy4.ConstMap) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Tuple(kodkod.instance.Tuple)

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