use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class BoundsComputer method allocatePrimSig.
// ==============================================================================================================//
/**
* Allocate relations for nonbuiltin PrimSigs bottom-up.
*/
private Expression allocatePrimSig(PrimSig sig) throws Err {
// Recursively allocate all children expressions, and form the union of
// them
Expression sum = null;
for (PrimSig child : sig.children()) {
Expression childexpr = allocatePrimSig(child);
if (sum == null) {
sum = childexpr;
continue;
}
// subsigs are disjoint
sol.addFormula(sum.intersection(childexpr).no(), child.isSubsig);
sum = sum.union(childexpr);
}
TupleSet lower = lb.get(sig).clone(), upper = ub.get(sig).clone();
if (sum == null) {
// If sig doesn't have children, then sig should make a fresh
// relation for itself
sum = sol.addRel(sig.label, lower, upper);
} else if (sig.isAbstract == null) {
// relation to act as the remainder.
for (PrimSig child : sig.children()) {
// Remove atoms that are KNOWN to be in a subsig;
// it's okay to mistakenly leave some atoms in, since we will
// never solve for the "remainder" relation directly;
// instead, we union the remainder with the children, then solve
// for the combined solution.
// (Thus, the more we can remove, the more efficient it gets,
// but it is not crucial for correctness)
TupleSet childTS = sol.query(false, sol.a2k(child), false);
lower.removeAll(childTS);
upper.removeAll(childTS);
}
sum = sum.union(sol.addRel(sig.label + " remainder", lower, upper));
}
sol.addSig(sig, sum);
return sum;
}
use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class ScopeComputer method sig2scope.
/**
* Sets the scope for a sig; returns true iff the sig's scope is changed by this
* call.
*/
private void sig2scope(Sig sig, int newValue) throws Err {
if (sig.builtin)
throw new ErrorSyntax(cmd.pos, "Cannot specify a scope for the builtin signature \"" + sig + "\"");
if (!(sig instanceof PrimSig))
throw new ErrorSyntax(cmd.pos, "Cannot specify a scope for a subset signature \"" + sig + "\"");
if (newValue < 0)
throw new ErrorSyntax(cmd.pos, "Cannot specify a negative scope for sig \"" + sig + "\"");
int old = sig2scope(sig);
if (old == newValue)
return;
if (old >= 0)
throw new ErrorSyntax(cmd.pos, "Sig \"" + sig + "\" already has a scope of " + old + ", so we cannot set it to be " + newValue);
sig2scope.put((PrimSig) sig, newValue);
rep.scope("Sig " + sig + " scope <= " + newValue + "\n");
}
use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class ScopeComputer method derive_scope_from_parent.
// ===========================================================================================================================//
/**
* If A is not toplevel, and we haven't been able to derive its scope yet, then
* give it its parent's scope.
*/
private boolean derive_scope_from_parent(Iterable<Sig> sigs) throws Err {
boolean changed = false;
Sig trouble = null;
for (Sig s : sigs) if (!s.builtin && !s.isTopLevel() && sig2scope(s) < 0 && (s instanceof PrimSig)) {
PrimSig p = ((PrimSig) s).parent;
int pb = sig2scope(p);
if (pb >= 0) {
sig2scope(s, pb);
changed = true;
} else {
trouble = s;
}
}
if (changed)
return true;
if (trouble == null)
return false;
throw new ErrorSyntax(cmd.pos, "You must specify a scope for sig \"" + trouble + "\"");
}
use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class ScopeComputer method computeLowerBound.
// ===========================================================================================================================//
/**
* Computes the number of atoms needed for each sig (and add these atoms to
* this.atoms)
*/
private int computeLowerBound(final PrimSig sig) throws Err {
if (sig.builtin)
return 0;
int n = sig2scope(sig), lower = 0;
boolean isExact = isExact(sig);
// First, figure out what atoms *MUST* be in this sig
for (PrimSig c : sig.children()) lower = lower + computeLowerBound(c);
// sig
if (n < lower) {
if (isExact)
rep.scope("Sig " + sig + " scope raised from ==" + n + " to be ==" + lower + "\n");
else
rep.scope("Sig " + sig + " scope raised from <=" + n + " to be <=" + lower + "\n");
n = lower;
sig2scope.put(sig, n);
}
// Add special overrides for "exactly" sigs
if (!isExact && cmd.additionalExactScopes.contains(sig)) {
isExact = true;
rep.scope("Sig " + sig + " forced to have exactly " + n + " atoms.\n");
makeExact(Pos.UNKNOWN, sig);
}
// Create atoms
if (n > lower && (isExact || sig.isTopLevel())) {
// Figure out how many new atoms to make
n = n - lower;
// Pick a name for them
String name = sig.label;
if (name.startsWith("this/"))
name = name.substring(5);
name = un.make(name);
// Now, generate each atom using the format "SIGNAME$INDEX"
// By prepending the index with 0 so that they're the same width, we
// ensure they sort lexicographically.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
String x = sb.delete(0, sb.length()).append(name).append('$').append(i).toString();
atoms.add(x);
lower++;
}
}
return lower;
}
use of edu.mit.csail.sdg.ast.Sig.PrimSig in project org.alloytools.alloy by AlloyTools.
the class A4SolutionReader method parseSig.
/**
* Parse sig/set.
*/
private Sig parseSig(String id, int depth) throws IOException, Err {
Sig ans = id2sig.get(id);
if (ans != null)
return ans;
XMLNode node = nmap.get(id);
if (node == null)
throw new IOException("Unknown SigID " + id + " encountered.");
if (!node.is("sig"))
throw new IOException("ID " + id + " is not a sig.");
String label = label(node);
Attr isAbstract = yes(node, "abstract") ? Attr.ABSTRACT : null;
Attr isOne = yes(node, "one") ? Attr.ONE : null;
Attr isLone = yes(node, "lone") ? Attr.LONE : null;
Attr isSome = yes(node, "some") ? Attr.SOME : null;
Attr isPrivate = yes(node, "private") ? Attr.PRIVATE : null;
Attr isMeta = yes(node, "meta") ? Attr.META : null;
Attr isEnum = yes(node, "enum") ? Attr.ENUM : null;
Attr isExact = yes(node, "exact") ? Attr.EXACT : null;
if (yes(node, "builtin")) {
if (label.equals(UNIV.label)) {
id2sig.put(id, UNIV);
return UNIV;
}
if (label.equals(SIGINT.label)) {
id2sig.put(id, SIGINT);
return SIGINT;
}
if (label.equals(SEQIDX.label)) {
id2sig.put(id, SEQIDX);
return SEQIDX;
}
if (label.equals(STRING.label)) {
id2sig.put(id, STRING);
return STRING;
}
throw new IOException("Unknown builtin sig: " + label + " (id=" + id + ")");
}
if (depth > nmap.size())
throw new IOException("Sig " + label + " (id=" + id + ") is in a cyclic inheritance relationship.");
List<Sig> parents = null;
TupleSet ts = factory.noneOf(1);
for (XMLNode sub : node) {
if (sub.is("atom")) {
ts.add(factory.tuple(sub.getAttribute("label")));
continue;
}
if (!sub.is("type"))
continue;
Sig parent = parseSig(sub.getAttribute("ID"), depth + 1);
if (parents == null)
parents = new ArrayList<Sig>();
parents.add(parent);
}
if (parents == null) {
String parentID = node.getAttribute("parentID");
Sig parent = parseSig(parentID, depth + 1);
if (!(parent instanceof PrimSig))
throw new IOException("Parent of sig " + label + " (id=" + id + ") must not be a subset sig.");
for (Expr choice : choices) if (choice instanceof PrimSig && parent == ((PrimSig) choice).parent && ((Sig) choice).label.equals(label)) {
ans = (Sig) choice;
choices.remove(choice);
break;
}
if (ans == null) {
ans = new PrimSig(label, (PrimSig) parent, isAbstract, isLone, isOne, isSome, isPrivate, isMeta, isEnum);
allsigs.add(ans);
}
} else {
for (Expr choice : choices) if (choice instanceof SubsetSig && ((Sig) choice).label.equals(label) && sameset(parents, ((SubsetSig) choice).parents)) {
ans = (Sig) choice;
choices.remove(choice);
break;
}
if (ans == null) {
ans = new SubsetSig(label, parents, isExact, isLone, isOne, isSome, isPrivate, isMeta);
allsigs.add(ans);
}
}
id2sig.put(id, ans);
expr2ts.put(ans, ts);
if (ans instanceof PrimSig) {
// Add the atoms in this SIG into all parent sigs
for (PrimSig ans2 = ((PrimSig) ans).parent; ans2 != null && !ans2.builtin; ans2 = ans2.parent) {
TupleSet ts2 = expr2ts.get(ans2);
if (ts2 == null)
ts2 = ts.clone();
else {
ts2 = ts2.clone();
ts2.addAll(ts);
}
expr2ts.put(ans2, ts2);
}
}
return ans;
}
Aggregations