Search in sources :

Example 1 with Field

use of edu.mit.csail.sdg.ast.Sig.Field 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 2 with Field

use of edu.mit.csail.sdg.ast.Sig.Field 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)

Example 3 with Field

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

the class CompModule method resolveMeta.

// ============================================================================================================================//
private static void resolveMeta(final CompModule root) throws Err {
    // Now, add the meta sigs and fields if needed
    Map<Sig, PrimSig> sig2meta = new LinkedHashMap<Sig, PrimSig>();
    Map<Field, PrimSig> field2meta = new LinkedHashMap<Field, PrimSig>();
    boolean hasMetaSig = false, hasMetaField = false;
    root.new2old.put(root.metaSig, root.metaSig);
    root.sigs.put(base(root.metaSig), root.metaSig);
    root.new2old.put(root.metaField, root.metaField);
    root.sigs.put(base(root.metaField), root.metaField);
    for (CompModule m : root.allModules) for (Sig s : new ArrayList<Sig>(m.sigs.values())) if (m != root || (s != root.metaSig && s != root.metaField)) {
        PrimSig ka = new PrimSig(s.label + "$", root.metaSig, Attr.ONE, PRIVATE.makenull(s.isPrivate), Attr.META);
        sig2meta.put(s, ka);
        ka.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "value", s);
        m.new2old.put(ka, ka);
        m.sigs.put(base(ka), ka);
        hasMetaSig = true;
        Expr allfields = ExprConstant.EMPTYNESS;
        for (Field field : s.getFields()) {
            Pos priv = field.isPrivate;
            if (priv == null)
                priv = s.isPrivate;
            PrimSig kb = new PrimSig(s.label + "$" + field.label, root.metaField, Attr.ONE, PRIVATE.makenull(priv), Attr.META);
            field2meta.put(field, kb);
            m.new2old.put(kb, kb);
            m.sigs.put(base(kb), kb);
            hasMetaField = true;
            kb.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "value", field);
            if (allfields == ExprConstant.EMPTYNESS)
                allfields = kb;
            else
                allfields = allfields.plus(kb);
        }
        ka.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "fields", allfields);
    }
    for (Map.Entry<Sig, PrimSig> e : sig2meta.entrySet()) {
        Expr expr = null;
        if ((e.getKey()) instanceof PrimSig) {
            PrimSig a = (PrimSig) (e.getKey());
            if (a.parent != null && a.parent != UNIV)
                expr = sig2meta.get(a.parent);
        }
        e.getValue().addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "parent", (expr == null ? ExprConstant.EMPTYNESS : expr));
    }
    for (Map.Entry<Sig, PrimSig> e : sig2meta.entrySet()) {
        Sig s = e.getKey();
        PrimSig s2 = e.getValue();
        Expr allfields = ExprConstant.EMPTYNESS;
        for (Field f : s.getFields()) {
            PrimSig metaF = field2meta.get(f);
            if (allfields == ExprConstant.EMPTYNESS)
                allfields = metaF;
            else
                allfields = allfields.plus(metaF);
        }
        if (s instanceof PrimSig)
            for (Sig c : (((PrimSig) s).descendents())) for (Field f : c.getFields()) {
                PrimSig metaF = field2meta.get(f);
                if (allfields == ExprConstant.EMPTYNESS)
                    allfields = metaF;
                else
                    allfields = allfields.plus(metaF);
            }
        s2.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "subfields", allfields);
    }
    if (hasMetaSig == false)
        root.facts.add(new Pair<String, Expr>("sig$fact", root.metaSig.no().and(root.metaField.no())));
    else if (hasMetaField == false)
        root.facts.add(new Pair<String, Expr>("sig$fact", root.metaField.no()));
}
Also used : LinkedHashMap(java.util.LinkedHashMap) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Sig(edu.mit.csail.sdg.ast.Sig) SubsetSig(edu.mit.csail.sdg.ast.Sig.SubsetSig) Field(edu.mit.csail.sdg.ast.Sig.Field) Expr(edu.mit.csail.sdg.ast.Expr) Pos(edu.mit.csail.sdg.alloy4.Pos) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) PrimSig(edu.mit.csail.sdg.ast.Sig.PrimSig) Pair(edu.mit.csail.sdg.alloy4.Pair)

Example 4 with Field

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

the class CompModule method resolveFieldDecl.

// ============================================================================================================================//
private static void resolveFieldDecl(CompModule res, final A4Reporter rep, final Sig s, final List<ErrorWarning> warns, boolean defined) throws Err {
    // When typechecking each field:
    // * it is allowed to refer to earlier fields in the same SIG or in any
    // visible ancestor sig
    // * it is allowed to refer to visible sigs
    // * it is NOT allowed to refer to any predicate or function
    // For example, if A.als opens B.als, and B/SIGX extends A/SIGY,
    // then B/SIGX's fields cannot refer to A/SIGY, nor any fields in
    // A/SIGY)
    final List<Decl> oldDecls = res.old2fields.get(res.new2old.get(s));
    if (oldDecls == null)
        return;
    final CompModule m = res.sig2module.get(s);
    final Context cx = new Context(m, warns);
    final ExprHasName dup = Decl.findDuplicateName(oldDecls);
    if (dup != null)
        throw new ErrorSyntax(dup.span(), "sig \"" + s + "\" cannot have 2 fields named \"" + dup.label + "\"");
    for (final Decl d : oldDecls) {
        if (d.expr.mult() != ExprUnary.Op.EXACTLYOF) {
            if (defined)
                continue;
        } else {
            if (!defined)
                continue;
        }
        // The name "this" does matter, since the parser and the typechecker
        // both refer to it as "this"
        cx.rootfield = d;
        cx.rootsig = s;
        cx.put("this", s.decl.get());
        Expr bound = cx.check(d.expr).resolve_as_set(warns);
        cx.remove("this");
        String[] names = new String[d.names.size()];
        for (int i = 0; i < names.length; i++) names[i] = d.names.get(i).label;
        Field[] fields = s.addTrickyField(d.span(), d.isPrivate, d.disjoint, d.disjoint2, null, names, bound);
        for (Field f : fields) {
            rep.typecheck("Sig " + s + ", Field " + f.label + ": " + f.type() + "\n");
        }
    }
}
Also used : Field(edu.mit.csail.sdg.ast.Sig.Field) ErrorSyntax(edu.mit.csail.sdg.alloy4.ErrorSyntax) Expr(edu.mit.csail.sdg.ast.Expr) ExprHasName(edu.mit.csail.sdg.ast.ExprHasName) Decl(edu.mit.csail.sdg.ast.Decl)

Example 5 with Field

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

the class BoundsComputer method sim.

// ==============================================================================================================//
/**
 * If ex is a simple combination of Relations, then return that combination,
 * else return null.
 */
private Expression sim(Expr ex) {
    while (ex instanceof ExprUnary) {
        ExprUnary u = (ExprUnary) ex;
        if (u.op != ExprUnary.Op.NOOP && u.op != ExprUnary.Op.EXACTLYOF)
            break;
        ex = u.sub;
    }
    if (ex instanceof ExprBinary) {
        ExprBinary b = (ExprBinary) ex;
        if (b.op == ExprBinary.Op.ARROW || b.op == ExprBinary.Op.PLUS || b.op == ExprBinary.Op.JOIN) {
            Expression left = sim(b.left);
            if (left == null)
                return null;
            Expression right = sim(b.right);
            if (right == null)
                return null;
            if (b.op == ExprBinary.Op.ARROW)
                return left.product(right);
            if (b.op == ExprBinary.Op.PLUS)
                return left.union(right);
            else
                return left.join(right);
        }
    }
    if (ex instanceof ExprConstant) {
        switch(((ExprConstant) ex).op) {
            case EMPTYNESS:
                return Expression.NONE;
        }
    }
    if (ex == Sig.NONE)
        return Expression.NONE;
    if (ex == Sig.SIGINT)
        return Expression.INTS;
    if (ex instanceof Sig)
        return sol.a2k((Sig) ex);
    if (ex instanceof Field)
        return sol.a2k((Field) ex);
    return null;
}
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) Field(edu.mit.csail.sdg.ast.Sig.Field) ExprBinary(edu.mit.csail.sdg.ast.ExprBinary) Expression(kodkod.ast.Expression) ExprUnary(edu.mit.csail.sdg.ast.ExprUnary) ExprConstant(edu.mit.csail.sdg.ast.ExprConstant)

Aggregations

Field (edu.mit.csail.sdg.ast.Sig.Field)19 Sig (edu.mit.csail.sdg.ast.Sig)17 PrimSig (edu.mit.csail.sdg.ast.Sig.PrimSig)12 SubsetSig (edu.mit.csail.sdg.ast.Sig.SubsetSig)9 Expr (edu.mit.csail.sdg.ast.Expr)8 ExprVar (edu.mit.csail.sdg.ast.ExprVar)7 HashMap (java.util.HashMap)6 LinkedHashMap (java.util.LinkedHashMap)6 TupleSet (kodkod.instance.TupleSet)5 Err (edu.mit.csail.sdg.alloy4.Err)4 Map (java.util.Map)4 ConstList (edu.mit.csail.sdg.alloy4.ConstList)3 SafeList (edu.mit.csail.sdg.alloy4.SafeList)3 Decl (edu.mit.csail.sdg.ast.Decl)3 ExprHasName (edu.mit.csail.sdg.ast.ExprHasName)3 ExprUnary (edu.mit.csail.sdg.ast.ExprUnary)3 IdentityHashMap (java.util.IdentityHashMap)3 ErrorFatal (edu.mit.csail.sdg.alloy4.ErrorFatal)2 Pair (edu.mit.csail.sdg.alloy4.Pair)2 Pos (edu.mit.csail.sdg.alloy4.Pos)2