/** * Calculates the Alloy constraint denoting the relation top test. Takes the shape "forall * whenvars : when => (forall sourcevars : sourcedomain => (exists targetvars+wherevars : * targetdomain && where))" Must be run after relation field is created (otherwise recursive calls * will fail) * * @return the Alloy constraint representing the relation * @throws EchoError */ private Expr calculateFact() throws EchoError { Expr fact = Sig.NONE.no(), sourceexpr = Sig.NONE.no(), postexpr = Sig.NONE.no(), whenexpr = Sig.NONE.no(); Decl[] arraydecl; ECondition postCondition = relation.getPost(); ECondition targetCondition = targetdomain.getCondition(); try { if (postCondition != null) { postCondition.initTranslation(parent_translator, var2varmodel(), modelparam2var, null); postexpr = (Expr) postCondition.translate(); } targetCondition.initTranslation(parent_translator, var2varmodel(), modelparam2var, null); Expr targetexpr = (Expr) targetCondition.translate(); targetexpr = targetexpr.and(postexpr); if (targetvar2alloydecl.size() == 1) targetexpr = targetexpr.forSome(targetvar2alloydecl.values().iterator().next()); else if (targetvar2alloydecl.size() > 1) { arraydecl = targetvar2alloydecl.values().toArray(new Decl[targetvar2alloydecl.size()]); targetexpr = targetexpr.forSome(arraydecl[0], Arrays.copyOfRange(arraydecl, 1, arraydecl.length)); } for (EModelDomain dom : sourcedomains) { ECondition sourceCondition = dom.getCondition(); sourceCondition.initTranslation(parent_translator, var2varmodel(), modelparam2var, null); sourceexpr = sourceexpr.and((Expr) sourceCondition.translate()); } fact = (sourceexpr.implies(targetexpr)); // for (Decl d : sourcevar2alloydecl.values()) // EchoReporter.getInstance().debug("Source var decl: "+d.names+"::"+d.expr); // for (Decl d : targetvar2alloydecl.values()) // EchoReporter.getInstance().debug("Target var decl: "+d.names+"::"+d.expr); if (sourcevar2alloydecl.size() == 1) { fact = fact.forAll(sourcevar2alloydecl.values().iterator().next()); } else if (sourcevar2alloydecl.size() > 1) { arraydecl = sourcevar2alloydecl.values().toArray(new Decl[sourcevar2alloydecl.size()]); fact = fact.forAll(arraydecl[0], Arrays.copyOfRange(arraydecl, 1, arraydecl.length)); } ECondition preCondition = relation.getPre(); if (preCondition != null) { preCondition.initTranslation(parent_translator, var2varmodel(), modelparam2var, null); whenexpr = (Expr) preCondition.translate(); fact = (whenexpr.implies(fact)); for (Decl d : whenvar2alloydecl.values()) fact = fact.forAll(d); } } catch (Err a) { throw new ErrorAlloy( ErrorAlloy.FAIL_CREATE_VAR, "Failed to create relation constraint variables: " + relation.getName(), a, Task.TRANSLATE_TRANSFORMATION); } return fact; }