|
|
|
@ -211,11 +211,17 @@ public class Modules2PTA |
|
|
|
pcValues.setValue(pc, pcVal); |
|
|
|
// RHS of guard should be conjunction of clock constraints (or true) |
|
|
|
// Split into parts, convert to constraints and add to new PTA transition |
|
|
|
// If expression is not (syntactically) convex, complain |
|
|
|
tr = pta.addTransition(pcVal, command.getSynch()); |
|
|
|
exprs = ParserUtils.splitConjunction(((ExpressionBinaryOp) command.getGuard()).getOperand2()); |
|
|
|
for (Expression ex : exprs) { |
|
|
|
if (!Expression.isTrue(ex)) { |
|
|
|
for (Constraint c : exprToConstraint(ex, pta)) { |
|
|
|
if (!(Expression.isTrue(ex) || Expression.isFalse(ex))) { |
|
|
|
checkIsSimpleClockConstraint(ex); |
|
|
|
} |
|
|
|
} |
|
|
|
for (Expression ex2 : exprs) { |
|
|
|
if (!Expression.isTrue(ex2)) { |
|
|
|
for (Constraint c : exprToConstraint(ex2, pta)) { |
|
|
|
tr.addGuardConstraint(c); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -253,7 +259,63 @@ public class Modules2PTA |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Convert a PRISM expression representing a clock constraint into |
|
|
|
* Check whether a PRISM expression (over clock variables) is a "simple" clock constraint, i.e. of the form |
|
|
|
* x~c or x~y where x and y are clocks, c is an integer-valued expression and ~ is one of <, <=, >=, >, =. |
|
|
|
* Throws an explanatory exception if not. |
|
|
|
* @param expr: The expression to be checked. |
|
|
|
*/ |
|
|
|
private void checkIsSimpleClockConstraint(Expression expr) throws PrismLangException |
|
|
|
{ |
|
|
|
ExpressionBinaryOp exprRelOp; |
|
|
|
Expression expr1, expr2; |
|
|
|
int op, clocks = 0; |
|
|
|
|
|
|
|
// Check is rel op |
|
|
|
if (!Expression.isRelOp(expr)) |
|
|
|
throw new PrismLangException("Invalid clock constraint \"" + expr + "\"", expr); |
|
|
|
// Split into parts |
|
|
|
exprRelOp = (ExpressionBinaryOp) expr; |
|
|
|
op = exprRelOp.getOperator(); |
|
|
|
expr1 = exprRelOp.getOperand1(); |
|
|
|
expr2 = exprRelOp.getOperand2(); |
|
|
|
// Check operator is of allowed type |
|
|
|
if (!ExpressionBinaryOp.isRelOp(op)) |
|
|
|
throw new PrismLangException("Can't use operator " + exprRelOp.getOperatorSymbol() + " in clock constraint \"" + expr + "\"", expr); |
|
|
|
if (op == ExpressionBinaryOp.NE) |
|
|
|
throw new PrismLangException("Can't use negation in clock constraint \"" + expr + "\"", expr); |
|
|
|
// LHS |
|
|
|
if (expr1.getType() instanceof TypeClock) { |
|
|
|
if (!(expr1 instanceof ExpressionVar)) { |
|
|
|
throw new PrismLangException("Invalid clock expression \"" + expr1 + "\"", expr1); |
|
|
|
} |
|
|
|
clocks++; |
|
|
|
} else if (expr1.getType() instanceof TypeInt) { |
|
|
|
if (!expr1.isConstant()) { |
|
|
|
throw new PrismLangException("Invalid clock constraint \"" + expr + "\"", expr); |
|
|
|
} |
|
|
|
} else { |
|
|
|
throw new PrismLangException("Invalid clock constraint \"" + expr + "\"", expr); |
|
|
|
} |
|
|
|
// RHS |
|
|
|
if (expr2.getType() instanceof TypeClock) { |
|
|
|
if (!(expr2 instanceof ExpressionVar)) { |
|
|
|
throw new PrismLangException("Invalid clock expression \"" + expr2 + "\"", expr2); |
|
|
|
} |
|
|
|
clocks++; |
|
|
|
} else if (expr2.getType() instanceof TypeInt) { |
|
|
|
if (!expr2.isConstant()) { |
|
|
|
throw new PrismLangException("Invalid clock constraint \"" + expr + "\"", expr); |
|
|
|
} |
|
|
|
} else { |
|
|
|
throw new PrismLangException("Invalid clock constraint \"" + expr + "\"", expr); |
|
|
|
} |
|
|
|
// Should be at least one clock |
|
|
|
if (clocks == 0) |
|
|
|
throw new PrismLangException("Invalid clock constraint \"" + expr + "\"", expr); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Convert a PRISM expression representing a (simple) clock constraint into |
|
|
|
* the Constraint data structures used in the pta package. |
|
|
|
* Actually creates a list of constraints (since e.g. x=c maps to multiple constraints) |
|
|
|
* @param expr: The expression to be converted. |
|
|
|
@ -378,8 +440,7 @@ public class Modules2PTA |
|
|
|
* @param pcVars: The variables that should be converted to a PC. |
|
|
|
* @param pcStates: An empty ArrayList into which PC value states will be stored. |
|
|
|
*/ |
|
|
|
private Module convertModuleToPCForm(Module module, List<String> pcVars, ArrayList<State> pcStates) |
|
|
|
throws PrismLangException |
|
|
|
private Module convertModuleToPCForm(Module module, List<String> pcVars, ArrayList<State> pcStates) throws PrismLangException |
|
|
|
{ |
|
|
|
// Info about variables in model to be used as program counter |
|
|
|
int pcNumVars; |
|
|
|
|