use of edu.mit.csail.sdg.ast.Sig.SubsetSig 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;
}
use of edu.mit.csail.sdg.ast.Sig.SubsetSig 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();
}
}
use of edu.mit.csail.sdg.ast.Sig.SubsetSig in project org.alloytools.alloy by AlloyTools.
the class BoundsComputer method allocateSubsetSig.
// ==============================================================================================================//
/**
* Allocate relations for SubsetSig top-down.
*/
private Expression allocateSubsetSig(SubsetSig sig) throws Err {
// We must not visit the same SubsetSig more than once, so if we've been
// here already, then return the old value right away
Expression sum = sol.a2k(sig);
if (sum != null && sum != Expression.NONE)
return sum;
// Recursively form the union of all parent expressions
TupleSet ts = factory.noneOf(1);
for (Sig parent : sig.parents) {
Expression p = (parent instanceof PrimSig) ? sol.a2k(parent) : allocateSubsetSig((SubsetSig) parent);
ts.addAll(sol.query(true, p, false));
if (sum == null)
sum = p;
else
sum = sum.union(p);
}
// If subset is exact, then just use the "sum" as is
if (sig.exact) {
sol.addSig(sig, sum);
return sum;
}
// Allocate a relation for this subset sig, then bound it
rep.bound("Sig " + sig + " in " + ts + "\n");
Relation r = sol.addRel(sig.label, null, ts);
sol.addSig(sig, r);
// Add a constraint that it is INDEED a subset of the union of its
// parents
sol.addFormula(r.in(sum), sig.isSubset);
return r;
}
use of edu.mit.csail.sdg.ast.Sig.SubsetSig 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.SubsetSig in project org.alloytools.alloy by AlloyTools.
the class A4SolutionWriter method writesig.
/**
* Write the given Sig.
*/
private A4TupleSet writesig(final Sig x) throws Err {
A4TupleSet ts = null, ts2 = null;
if (x == Sig.NONE)
// should not happen, but we test for it anyway
return null;
if (sol == null && x.isMeta != null)
// When writing the metamodel, skip the metamodel sigs!
return null;
if (x instanceof PrimSig)
for (final PrimSig sub : children((PrimSig) x)) {
A4TupleSet ts3 = writesig(sub);
if (ts2 == null)
ts2 = ts3;
else
ts2 = ts2.plus(ts3);
}
if (rep != null)
rep.write(x);
Util.encodeXMLs(out, "\n<sig label=\"", x.label, "\" ID=\"", map(x));
if (x instanceof PrimSig && x != Sig.UNIV)
Util.encodeXMLs(out, "\" parentID=\"", map(((PrimSig) x).parent));
if (x.builtin)
out.print("\" builtin=\"yes");
if (x.isAbstract != null)
out.print("\" abstract=\"yes");
if (x.isOne != null)
out.print("\" one=\"yes");
if (x.isLone != null)
out.print("\" lone=\"yes");
if (x.isSome != null)
out.print("\" some=\"yes");
if (x.isPrivate != null)
out.print("\" private=\"yes");
if (x.isMeta != null)
out.print("\" meta=\"yes");
if (x instanceof SubsetSig && ((SubsetSig) x).exact)
out.print("\" exact=\"yes");
if (x.isEnum != null)
out.print("\" enum=\"yes");
out.print("\">\n");
try {
if (sol != null && x != Sig.UNIV && x != Sig.SIGINT && x != Sig.SEQIDX) {
ts = (sol.eval(x));
for (A4Tuple t : ts.minus(ts2)) Util.encodeXMLs(out, " <atom label=\"", t.atom(0), "\"/>\n");
}
} catch (Throwable ex) {
throw new ErrorFatal("Error evaluating sig " + x.label, ex);
}
if (x instanceof SubsetSig)
for (Sig p : ((SubsetSig) x).parents) Util.encodeXMLs(out, " <type ID=\"", map(p), "\"/>\n");
out.print("</sig>\n");
for (Field field : x.getFields()) writeField(field);
return ts;
}
Aggregations