/** * Generates the relation field over the model sigs for called relations Must be run before the * relation constraint is created (otherwise recursive calls will fail) * * @return the Alloy field for this relation * @throws EchoError * @todo Support for n models */ private Field addRelationFields() throws EchoError { Field field = null; Decl fst = rootvar2alloydecl.get(relation.getDomains().get(0).getRootVariable().getName()); /*Decl snd = rootvar2alloydecl.get(relation.getDomains().get(1) .getVariable().getName());*/ try { Sig s = (Sig) fst.expr.type().toExpr(); for (Field f : s.getFields()) { if (f.label.equals(AlloyUtil.relationFieldName(relation, dependency.target))) field = f; } if (field == null) { field = s.addField( AlloyUtil.relationFieldName(relation, dependency.target), /*type.setOf()*/ Sig.UNIV.setOf()); } } catch (Err a) { throw new ErrorAlloy( ErrorAlloy.FAIL_CREATE_FIELD, "Failed to create relation field representation: " + relation.getName(), a, Task.TRANSLATE_TRANSFORMATION); } return field; }
/** * adds to the transformation translator the constraint defining the field of this sub relation * * @param fact the constraint defining this relation * @param field the field representing this sub relation * @throws EchoError */ private void addRelationDef(Expr fact, Field field) throws EchoError { Decl fst = rootvar2alloydecl.get(relation.getDomains().get(0).getRootVariable().getName()); Decl snd = rootvar2alloydecl.get(relation.getDomains().get(1).getRootVariable().getName()); Func f; try { Expr e = field.equal(fact.comprehensionOver(fst, snd)); f = new Func(null, field.label + "def", model_params_decls, null, e); transformation_translator.addSubRelationDef(f); } catch (Err a) { throw new ErrorAlloy( ErrorAlloy.FAIL_CREATE_FUNC, "Failed to create sub relation field constraint: " + relation.getName(), a, Task.TRANSLATE_TRANSFORMATION); } }
/** * adds to the transformation translator the constraint defining this top relation * * @param fact the constraint defining this relation * @throws EchoError */ private void addRelationPred(Expr fact) throws EchoError { try { transformation_translator.addTopRelationCall( new Func( null, AlloyUtil.relationPredName(relation, dependency.target), model_params_decls, null, fact)); } catch (Err a) { throw new ErrorAlloy( ErrorAlloy.FAIL_CREATE_FUNC, "Failed to create top relation constraint function: " + relation.getName(), a, Task.TRANSLATE_TRANSFORMATION); } }
/** * adds to the transformation translator the field representing this sub relation * * @throws EchoError */ private Field addRelationField() throws EchoError { Field field = null; try { field = addRelationFields(); transformation_translator.addSubRelationCall( new Func( null, AlloyUtil.relationFieldName(relation, dependency.target), model_params_decls, field.type().toExpr(), field)); } catch (Err a) { throw new ErrorAlloy( ErrorAlloy.FAIL_CREATE_FUNC, "Failed to create sub relation constraint function: " + relation.getName(), a, Task.TRANSLATE_TRANSFORMATION); } return field; }
/** * 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; }