/** * 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); } }
/** * Constructs a new relation to Alloy translator. Translates a relation (top or non top) to Alloy * in a given direction. * * @param relation the relation being translated * @param top whether the relation is top or not * @throws EchoError */ Relation2Alloy( EAlloyTransformation transformation_translator, Boolean top, Relation2Alloy parent_translator, EDependency dependency, ERelation relation) throws EchoError { this.relation = relation; this.dependency = dependency; this.top = top; this.transformation_translator = transformation_translator; this.parent_translator = top ? this : parent_translator; for (EModelParameter mdl : relation.getTransformation().getModels()) { Decl d; String metamodelID = mdl.getMetamodel().ID; try { d = AlloyEchoTranslator.getInstance() .getMetamodel(metamodelID) .sig_metamodel .oneOf(mdl.getName()); } catch (Err a) { throw new ErrorAlloy( ErrorAlloy.FAIL_CREATE_VAR, "Failed to create transformation model variable: " + mdl.getName(), a, Task.TRANSLATE_TRANSFORMATION); } model_params_decls.add(d); modelparam2var.put(mdl.getName(), d.get()); var2model.put(d.get().label, null); var2var.put(d.get().label, d.get()); } initVariableLists(); Field field = null; if (!top) field = addRelationField(); Expr fact = calculateFact(); AlloyOptimizations opt = new AlloyOptimizations(); if (EchoOptionsSetup.getInstance().isOptimize() && true) { fact = opt.trading(fact); fact = opt.onePoint(fact); } EchoReporter.getInstance().debug("Post-opt: " + fact); if (top) addRelationPred(fact); else addRelationDef(fact, field); }
/** * 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; }
/** * Initializes the variable lists and generates the respective Alloy declarations. * * @throws EchoError * @todo Support fom <code>CollectionTemplateExp</code> */ private void initVariableLists() throws EchoError { Map<EVariable, String> whenvar2model = new HashMap<EVariable, String>(); Map<EVariable, String> sourcevar2model = new HashMap<EVariable, String>(); Map<EVariable, String> targetvar2model = new HashMap<EVariable, String>(); for (EModelDomain dom : relation.getDomains()) { rootvariables.put(dom.getRootVariable(), dom.getModel().getName()); if (dependency.target.equals(dom)) targetdomain = dom; else sourcedomains.add(dom); } ECondition preCondition = relation.getPre(); if (preCondition != null) whenvar2model = preCondition.getVariables(null); for (EModelDomain dom : sourcedomains) { ECondition cond = dom.getCondition(); sourcevar2model.putAll(cond.getVariables(dom.getModel().getName())); } for (EVariable x : whenvar2model.keySet()) { whenvar2model.put(x, sourcevar2model.get(x)); sourcevar2model.remove(x); } ECondition temp = targetdomain.getCondition(); targetvar2model = temp.getVariables(targetdomain.getModel().getName()); ECondition postCondition = relation.getPost(); if (postCondition != null) for (EVariable x : postCondition.getVariables(null).keySet()) if (targetvar2model.get(x) == null) targetvar2model.put(x, null); for (EVariable x : sourcevar2model.keySet()) { if (sourcevar2model.get(x) == null) sourcevar2model.put(x, targetvar2model.get(x)); targetvar2model.remove(x); } for (EVariable x : whenvar2model.keySet()) { if (whenvar2model.get(x) == null) whenvar2model.put(x, targetvar2model.get(x)); targetvar2model.remove(x); } if (!top) for (EVariable x : rootvariables.keySet()) { whenvar2model.remove(x); targetvar2model.remove(x); sourcevar2model.remove(x); } for (EVariable s : sourcevar2model.keySet()) var2model.put(s.getName(), sourcevar2model.get(s)); for (EVariable s : targetvar2model.keySet()) var2model.put(s.getName(), targetvar2model.get(s)); for (EVariable s : whenvar2model.keySet()) var2model.put(s.getName(), whenvar2model.get(s)); if (!top) for (EVariable s : rootvariables.keySet()) var2model.put(s.getName(), rootvariables.get(s)); sourcevar2alloydecl = AlloyUtil.variableListToExpr(sourcevar2model.keySet(), var2varmodel(), modelparam2var); for (String s : sourcevar2alloydecl.keySet()) var2var.put(s, sourcevar2alloydecl.get(s).get()); targetvar2alloydecl = AlloyUtil.variableListToExpr(targetvar2model.keySet(), var2varmodel(), modelparam2var); for (String s : targetvar2alloydecl.keySet()) var2var.put(s, targetvar2alloydecl.get(s).get()); whenvar2alloydecl = AlloyUtil.variableListToExpr(whenvar2model.keySet(), var2varmodel(), modelparam2var); for (String s : whenvar2alloydecl.keySet()) var2var.put(s, whenvar2alloydecl.get(s).get()); rootvar2alloydecl = AlloyUtil.variableListToExpr(rootvariables.keySet(), var2varmodel(), modelparam2var); if (!top) for (String s : rootvar2alloydecl.keySet()) var2var.put(s, rootvar2alloydecl.get(s).get()); }
/** * 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; }