use of kodkod.ast.Expression in project org.alloytools.alloy by AlloyTools.
the class TranslateAlloyToKodkod method visit_qt.
/**
* Helper method that translates the quantification expression "op vars | sub"
*/
private Object visit_qt(final ExprQt.Op op, final ConstList<Decl> xvars, final Expr sub) throws Err {
if (op == ExprQt.Op.NO) {
return visit_qt(ExprQt.Op.ALL, xvars, sub.not());
}
if (op == ExprQt.Op.ONE || op == ExprQt.Op.LONE) {
boolean ok = true;
for (int i = 0; i < xvars.size(); i++) {
Expr v = addOne(xvars.get(i).expr).deNOP();
if (v.type().arity() != 1 || v.mult() != ExprUnary.Op.ONEOF) {
ok = false;
break;
}
}
if (op == ExprQt.Op.ONE && ok)
return ((Expression) visit_qt(ExprQt.Op.COMPREHENSION, xvars, sub)).one();
if (op == ExprQt.Op.LONE && ok)
return ((Expression) visit_qt(ExprQt.Op.COMPREHENSION, xvars, sub)).lone();
}
if (op == ExprQt.Op.ONE) {
Formula f1 = (Formula) visit_qt(ExprQt.Op.LONE, xvars, sub);
Formula f2 = (Formula) visit_qt(ExprQt.Op.SOME, xvars, sub);
return f1.and(f2);
}
if (op == ExprQt.Op.LONE) {
QuantifiedFormula p1 = (QuantifiedFormula) visit_qt(ExprQt.Op.ALL, xvars, sub);
QuantifiedFormula p2 = (QuantifiedFormula) visit_qt(ExprQt.Op.ALL, xvars, sub);
Decls s1 = p1.decls(), s2 = p2.decls(), decls = null;
Formula f1 = p1.formula(), f2 = p2.formula();
Formula[] conjuncts = new Formula[s1.size()];
for (int i = 0; i < conjuncts.length; i++) {
kodkod.ast.Decl d1 = s1.get(i), d2 = s2.get(i);
conjuncts[i] = d1.variable().eq(d2.variable());
if (decls == null)
decls = d1.and(d2);
else
decls = decls.and(d1).and(d2);
}
return f1.and(f2).implies(Formula.and(conjuncts)).forAll(decls);
}
Decls dd = null;
List<Formula> guards = new ArrayList<Formula>();
for (Decl dep : xvars) {
final Expr dexexpr = addOne(dep.expr);
final Expression dv = cset(dexexpr);
for (ExprHasName dex : dep.names) {
final Variable v = Variable.nary(skolem(dex.label), dex.type().arity());
final kodkod.ast.Decl newd;
env.put((ExprVar) dex, v);
if (dex.type().arity() != 1) {
guards.add(isIn(v, dexexpr));
newd = v.setOf(dv);
} else
switch(dexexpr.mult()) {
case SETOF:
newd = v.setOf(dv);
break;
case SOMEOF:
newd = v.someOf(dv);
break;
case LONEOF:
newd = v.loneOf(dv);
break;
default:
newd = v.oneOf(dv);
}
if (frame != null)
frame.kv2typepos(v, dex.type(), dex.pos);
if (dd == null)
dd = newd;
else
dd = dd.and(newd);
}
}
final Formula ans = (op == ExprQt.Op.SUM) ? null : cform(sub);
final IntExpression ians = (op != ExprQt.Op.SUM) ? null : cint(sub);
for (Decl d : xvars) for (ExprHasName v : d.names) env.remove((ExprVar) v);
if (op == ExprQt.Op.COMPREHENSION)
// guards.size()==0, since each var
return ans.comprehension(dd);
// has to be unary
if (op == ExprQt.Op.SUM)
// guards.size()==0, since each var has to be
return ians.sum(dd);
// unary
if (op == ExprQt.Op.SOME) {
if (guards.size() == 0)
return ans.forSome(dd);
guards.add(ans);
return Formula.and(guards).forSome(dd);
} else {
if (guards.size() == 0)
return ans.forAll(dd);
return Formula.and(guards).implies(ans).forAll(dd);
}
}
use of kodkod.ast.Expression in project org.alloytools.alloy by AlloyTools.
the class TranslateAlloyToKodkod method visit.
/**
* {@inheritDoc}
*/
@Override
public Object visit(ExprList x) throws Err {
if (x.op == ExprList.Op.AND || x.op == ExprList.Op.OR) {
if (x.args.size() == 0)
return (x.op == ExprList.Op.AND) ? Formula.TRUE : Formula.FALSE;
Formula answer = getSingleFormula(x.op == ExprList.Op.AND, 1, x.args);
return k2pos(answer, x);
}
if (x.op == ExprList.Op.TOTALORDER) {
Expression elem = cset(x.args.get(0)), first = cset(x.args.get(1)), next = cset(x.args.get(2));
if (elem instanceof Relation && first instanceof Relation && next instanceof Relation) {
Relation lst = frame.addRel("", null, frame.query(true, elem, false));
totalOrderPredicates.add((Relation) elem);
totalOrderPredicates.add((Relation) first);
totalOrderPredicates.add(lst);
totalOrderPredicates.add((Relation) next);
return k2pos(((Relation) next).totalOrder((Relation) elem, (Relation) first, lst), x);
}
// every
Formula f1 = elem.in(first.join(next.reflexiveClosure()));
// element
// is in
// the
// total
// order
// first element has no
Formula f2 = next.join(first).no();
// predecessor
Variable e = Variable.unary("v" + Integer.toString(cnt++));
// each element
Formula f3 = e.eq(first).or(next.join(e).one());
// (except the
// first) has
// one
// predecessor
// each
Formula f4 = e.eq(elem.difference(next.join(elem))).or(e.join(next).one());
// element
// (except
// the
// last)
// has
// one
// successor
// there are no
Formula f5 = e.in(e.join(next.closure())).not();
// cycles
return k2pos(f3.and(f4).and(f5).forAll(e.oneOf(elem)).and(f1).and(f2), x);
}
// This says no(a&b) and no((a+b)&c) and no((a+b+c)&d)...
// Empirically this seems to be more efficient than "no(a&b) and no(a&c)
// and no(b&c)"
Formula answer = null;
Expression a = null;
for (Expr arg : x.args) {
Expression b = cset(arg);
if (a == null) {
a = b;
continue;
}
if (answer == null)
answer = a.intersection(b).no();
else
answer = a.intersection(b).no().and(answer);
a = a.union(b);
}
if (answer != null)
return k2pos(answer, x);
else
return Formula.TRUE;
}
use of kodkod.ast.Expression in project org.alloytools.alloy by AlloyTools.
the class TranslateAlloyToKodkod method alloy2kodkod.
/**
* Translate the Alloy expression into an equivalent Kodkod Expression or
* IntExpression or Formula object.
*
* @param sol - an existing satisfiable A4Solution object
* @param expr - this is the Alloy expression we want to translate
*/
public static Object alloy2kodkod(A4Solution sol, Expr expr) throws Err {
if (expr.ambiguous && !expr.errors.isEmpty())
expr = expr.resolve(expr.type(), null);
if (!expr.errors.isEmpty())
throw expr.errors.pick();
TranslateAlloyToKodkod tr = new TranslateAlloyToKodkod(sol.getBitwidth(), sol.unrolls(), sol.a2k(), sol.s2k());
Object ans;
try {
ans = tr.visitThis(expr);
} catch (UnsatisfiedLinkError ex) {
throw new ErrorFatal("The required JNI library cannot be found: " + ex.toString().trim());
} catch (CapacityExceededException ex) {
throw rethrow(ex);
} catch (HigherOrderDeclException ex) {
throw new ErrorType("Analysis cannot be performed since it requires higher-order quantification that could not be skolemized.");
} catch (Throwable ex) {
if (ex instanceof Err)
throw (Err) ex;
throw new ErrorFatal("Unknown exception occurred: " + ex, ex);
}
if ((ans instanceof IntExpression) || (ans instanceof Formula) || (ans instanceof Expression))
return ans;
throw new ErrorFatal("Unknown internal error encountered in the evaluator.");
}
use of kodkod.ast.Expression in project org.alloytools.alloy by AlloyTools.
the class TranslateAlloyToKodkod method visit.
/**
* {@inheritDoc}
*/
@Override
public Object visit(ExprCall x) throws Err {
final Func f = x.fun;
final Object candidate = f.count() == 0 ? cacheForConstants.get(f) : null;
if (candidate != null)
return candidate;
final Expr body = f.getBody();
if (body.type().arity() < 0 || body.type().arity() != f.returnDecl.type().arity())
throw new ErrorType(body.span(), "Function return value not fully resolved.");
final int n = f.count();
int maxRecursion = unrolls;
for (Func ff : current_function) if (ff == f) {
if (maxRecursion < 0) {
throw new ErrorSyntax(x.span(), "" + f + " cannot call itself recursively!");
}
if (maxRecursion == 0) {
Type t = f.returnDecl.type();
if (t.is_bool)
return Formula.FALSE;
if (t.is_int())
return IntConstant.constant(0);
int i = t.arity();
Expression ans = Expression.NONE;
while (i > 1) {
ans = ans.product(Expression.NONE);
i--;
}
return ans;
}
maxRecursion--;
}
Env<ExprVar, Object> newenv = new Env<ExprVar, Object>();
for (int i = 0; i < n; i++) newenv.put(f.get(i), cset(x.args.get(i)));
Env<ExprVar, Object> oldenv = env;
env = newenv;
current_function.add(f);
Object ans = visitThis(body);
env = oldenv;
current_function.remove(current_function.size() - 1);
if (ans instanceof Formula)
k2pos((Formula) ans, x);
if (f.count() == 0)
cacheForConstants.put(f, ans);
return ans;
}
use of kodkod.ast.Expression in project org.alloytools.alloy by AlloyTools.
the class AbstractReplacer method visit.
/**
* Calls lookup(intExpr) and returns the cached value, if any. If a replacement
* has not been cached, visits the expression's child. If nothing changes, the
* argument is cached and returned, otherwise a replacement expression is cached
* and returned.
*
* @return { i: ExprToIntCast | i.expression =
* intExpr.expression.accept(delegate) && i.op = intExpr.op}
*/
@Override
public IntExpression visit(ExprToIntCast intExpr) {
IntExpression ret = lookup(intExpr);
if (ret != null)
return ret;
final Expression expr = intExpr.expression().accept(delegate);
ret = expr == intExpr.expression() ? intExpr : expr.apply(intExpr.op());
return cache(intExpr, ret);
}
Aggregations