use of edu.mit.csail.sdg.ast.Decl 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.Decl 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");
}
}
}
use of edu.mit.csail.sdg.ast.Decl in project org.alloytools.alloy by AlloyTools.
the class CompModule method resolveFuncBody.
/**
* Each Func's body will now be typechecked Expr object.
*/
private JoinableList<Err> resolveFuncBody(A4Reporter rep, JoinableList<Err> errors, List<ErrorWarning> warns) throws Err {
for (ArrayList<Func> entry : funcs.values()) for (Func ff : entry) {
Context cx = new Context(this, warns);
cx.rootfunbody = ff;
for (Decl d : ff.decls) for (ExprHasName n : d.names) cx.put(n.label, n);
Expr newBody = cx.check(ff.getBody());
if (ff.isPred)
newBody = newBody.resolve_as_formula(warns);
else
newBody = newBody.resolve_as_set(warns);
errors = errors.make(newBody.errors);
if (!newBody.errors.isEmpty())
continue;
try {
ff.setBody(newBody);
} catch (Err er) {
errors = errors.make(er);
continue;
}
if (warns != null && ff.returnDecl.type().hasTuple() && newBody.type().hasTuple() && !newBody.type().intersects(ff.returnDecl.type()))
warns.add(new ErrorWarning(newBody.span(), "Function return value is disjoint from its return type.\n" + "Function body has type " + newBody.type() + "\n" + "but the return type is " + ff.returnDecl.type()));
// else if (warns!=null && Version.experimental &&
// !newBody.type.isSubtypeOf(ff.returnDecl.type))
// warns.add(new ErrorWarning(newBody.span(),
// "Function may return a tuple not in its declared return
// type.\n"
// +"The Alloy Analyzer's analysis may be unsound\n"
// +"if it returns a tuple outside its declared return type.\n"
// +"Function body has type "+newBody.type+"\nbut the return
// type is "+ff.returnDecl.type));
rep.typecheck(ff.toString() + ", BODY:" + newBody.type() + "\n");
}
return errors;
}
use of edu.mit.csail.sdg.ast.Decl in project org.alloytools.alloy by AlloyTools.
the class TranslateAlloyToKodkod method makeFacts.
/**
* Conjoin the constraints for "field declarations" and "fact" paragraphs
*/
private void makeFacts(Expr facts) throws Err {
rep.debug("Generating facts...\n");
// convert into a form that hopefully gives better unsat core
facts = (new ConvToConjunction()).visitThis(facts);
// add the field facts and appended facts
for (Sig s : frame.getAllReachableSigs()) {
for (Decl d : s.getFieldDecls()) {
k2pos_enabled = false;
for (ExprHasName n : d.names) {
Field f = (Field) n;
Expr form = s.decl.get().join(f).in(d.expr);
form = s.isOne == null ? form.forAll(s.decl) : ExprLet.make(null, (ExprVar) (s.decl.get()), s, form);
frame.addFormula(cform(form), f);
// subset of s.
if (s.isOne == null) {
Expression sr = a2k(s), fr = a2k(f);
for (int i = f.type().arity(); i > 1; i--) fr = fr.join(Expression.UNIV);
frame.addFormula(fr.in(sr), f);
}
}
if (s.isOne == null && 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());
frame.addFormula(cform(formula.forAll(that).forAll(s.decl)), d.disjoint2);
}
if (d.names.size() > 1 && d.disjoint != null) {
frame.addFormula(cform(ExprList.makeDISJOINT(d.disjoint, null, d.names)), d.disjoint);
}
}
k2pos_enabled = true;
for (Expr f : s.getFacts()) {
Expr form = s.isOne == null ? f.forAll(s.decl) : ExprLet.make(null, (ExprVar) (s.decl.get()), s, f);
frame.addFormula(cform(form), f);
}
}
k2pos_enabled = true;
recursiveAddFormula(facts);
}
use of edu.mit.csail.sdg.ast.Decl in project org.alloytools.alloy by AlloyTools.
the class ExampleUsingTheAPI method main.
public static void main(String[] args) throws Err {
// Chooses the Alloy4 options
A4Options opt = new A4Options();
opt.solver = A4Options.SatSolver.SAT4J;
// abstract sig A {}
PrimSig A = new PrimSig("A", Attr.ABSTRACT);
// sig B {}
PrimSig B = new PrimSig("B");
// one sig A1 extends A {}
PrimSig A1 = new PrimSig("A1", A, Attr.ONE);
// one sig A2 extends A {}
PrimSig A2 = new PrimSig("A2", A, Attr.ONE);
// A { f: B lone->lone B }
Expr f = A.addField("f", B.lone_arrow_lone(B));
// Since (B lone->lone B) is not unary, the default is "setOf", meaning
// "f:set (B lone->lone B)"
// A { g: B }
Expr g = A.addField("g", B);
// The line above is the same as: A.addField(null, "g", B.oneOf()) since
// B is unary.
// If you want "setOf", you need: A.addField(null, "g", B.setOf())
// pred someG { some g }
Func someG = new Func(null, "SomeG", null, null, g.some());
// pred atMostThree[x:univ, y:univ] { #(x+y) >= 3 }
Decl x = UNIV.oneOf("x");
Decl y = UNIV.oneOf("y");
Expr body = x.get().plus(y.get()).cardinality().lte(ExprConstant.makeNUMBER(3));
Func atMost3 = new Func(null, "atMost3", Util.asList(x, y), null, body);
List<Sig> sigs = Arrays.asList(new Sig[] { A, B, A1, A2 });
// run { some A && atMostThree[B,B] } for 3 but 3 int, 3 seq
Expr expr1 = A.some().and(atMost3.call(B, B));
Command cmd1 = new Command(false, 3, 3, 3, expr1);
A4Solution sol1 = TranslateAlloyToKodkod.execute_command(NOP, sigs, cmd1, opt);
System.out.println("[Solution1]:");
System.out.println(sol1.toString());
// run { some f && SomeG[] } for 3 but 2 int, 1 seq, 5 A, exactly 6 B
Expr expr2 = f.some().and(someG.call());
Command cmd2 = new Command(false, 3, 2, 1, expr2);
cmd2 = cmd2.change(A, false, 1);
cmd2 = cmd2.change(B, true, 1);
A4Solution sol2 = TranslateAlloyToKodkod.execute_command(NOP, sigs, cmd2, opt);
while (sol2.satisfiable()) {
System.out.println("[Solution2]:");
System.out.println(sol2.toString());
sol2 = sol2.next();
}
}
Aggregations