You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
307 lines
8.2 KiB
307 lines
8.2 KiB
//==============================================================================
|
|
//
|
|
// Copyright (c) 2002-
|
|
// Authors:
|
|
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// This file is part of PRISM.
|
|
//
|
|
// PRISM is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// PRISM is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with PRISM; if not, write to the Free Software Foundation,
|
|
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
//==============================================================================
|
|
|
|
package parser.ast;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import parser.*;
|
|
import parser.type.*;
|
|
import parser.visitor.*;
|
|
import prism.PrismLangException;
|
|
|
|
/**
|
|
* Class to store a single update, i.e. a mapping from variables to expressions.
|
|
* e.g. (s'=1)&(x'=x+1)
|
|
*/
|
|
public class Update extends ASTElement
|
|
{
|
|
// Lists of variable/expression pairs (and types)
|
|
private ArrayList<String> vars;
|
|
private ArrayList<Expression> exprs;
|
|
private ArrayList<Type> types;
|
|
// We also store an ExpressionIdent to match each variable.
|
|
// This is to just to provide positional info.
|
|
private ArrayList<ExpressionIdent> varIdents;
|
|
// The indices of each variable in the model to which it belongs
|
|
private ArrayList<Integer> indices;
|
|
// Parent Updates object
|
|
private Updates parent;
|
|
|
|
/**
|
|
* Create an empty update.
|
|
*/
|
|
public Update()
|
|
{
|
|
vars = new ArrayList<String>();
|
|
exprs = new ArrayList<Expression>();
|
|
types = new ArrayList<Type>();
|
|
varIdents = new ArrayList<ExpressionIdent>();
|
|
indices = new ArrayList<Integer>();
|
|
}
|
|
|
|
// Set methods
|
|
|
|
public void addElement(ExpressionIdent v, Expression e)
|
|
{
|
|
vars.add(v.getName());
|
|
exprs.add(e);
|
|
types.add(null); // Type currently unknown
|
|
varIdents.add(v);
|
|
indices.add(-1); // Index currently unknown
|
|
}
|
|
|
|
public void setVar(int i, ExpressionIdent v)
|
|
{
|
|
vars.set(i, v.getName());
|
|
varIdents.set(i, v);
|
|
}
|
|
|
|
public void setExpression(int i, Expression e)
|
|
{
|
|
exprs.set(i, e);
|
|
}
|
|
|
|
public void setType(int i, Type t)
|
|
{
|
|
types.set(i, t);
|
|
}
|
|
|
|
public void setVarIndex(int i, int index)
|
|
{
|
|
indices.set(i, index);
|
|
}
|
|
|
|
public void setParent(Updates u)
|
|
{
|
|
parent = u;
|
|
}
|
|
|
|
// Get methods
|
|
|
|
public int getNumElements()
|
|
{
|
|
return vars.size();
|
|
}
|
|
|
|
public String getVar(int i)
|
|
{
|
|
return vars.get(i);
|
|
}
|
|
|
|
public Expression getExpression(int i)
|
|
{
|
|
return exprs.get(i);
|
|
}
|
|
|
|
public Type getType(int i)
|
|
{
|
|
return types.get(i);
|
|
}
|
|
|
|
public ExpressionIdent getVarIdent(int i)
|
|
{
|
|
return varIdents.get(i);
|
|
}
|
|
|
|
public int getVarIndex(int i)
|
|
{
|
|
return indices.get(i);
|
|
}
|
|
|
|
public Updates getParent()
|
|
{
|
|
return parent;
|
|
}
|
|
|
|
/**
|
|
* Execute this update, based on variable values specified as a Values object,
|
|
* returning the result as a new Values object copied from the existing one.
|
|
* Values of any constants should also be provided.
|
|
* @param constantValues Values for constants
|
|
* @param oldValues Variable values in current state
|
|
*/
|
|
public Values update(Values constantValues, Values oldValues) throws PrismLangException
|
|
{
|
|
int i, n;
|
|
Values res;
|
|
res = new Values(oldValues);
|
|
n = exprs.size();
|
|
for (i = 0; i < n; i++) {
|
|
res.setValue(getVar(i), getExpression(i).evaluate(constantValues, oldValues));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Execute this update, based on variable values specified as a Values object,
|
|
* applying changes in variables to a second Values object.
|
|
* Values of any constants should also be provided.
|
|
* @param constantValues Values for constants
|
|
* @param oldValues Variable values in current state
|
|
* @param newValues Values object to apply changes to
|
|
*/
|
|
public void update(Values constantValues, Values oldValues, Values newValues) throws PrismLangException
|
|
{
|
|
int i, n;
|
|
n = exprs.size();
|
|
for (i = 0; i < n; i++) {
|
|
newValues.setValue(getVar(i), getExpression(i).evaluate(constantValues, oldValues));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute this update, based on variable values specified as a State object,
|
|
* returning the result as a new State object copied from the existing one.
|
|
* It is assumed that any constants have already been defined.
|
|
* @param oldState Variable values in current state
|
|
*/
|
|
public State update(State oldState) throws PrismLangException
|
|
{
|
|
int i, n;
|
|
State res;
|
|
res = new State(oldState);
|
|
n = exprs.size();
|
|
for (i = 0; i < n; i++) {
|
|
res.setValue(getVarIndex(i), getExpression(i).evaluate(oldState));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Execute this update, based on variable values specified as a State object.
|
|
* Apply changes in variables to a provided copy of the State object.
|
|
* (i.e. oldState and newState should be equal when passed in.)
|
|
* It is assumed that any constants have already been defined.
|
|
* @param oldState Variable values in current state
|
|
* @param newState State object to apply changes to
|
|
*/
|
|
public void update(State oldState, State newState) throws PrismLangException
|
|
{
|
|
int i, n;
|
|
n = exprs.size();
|
|
for (i = 0; i < n; i++) {
|
|
newState.setValue(getVarIndex(i), getExpression(i).evaluate(oldState));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute this update, based on variable values specified as a State object.
|
|
* Apply changes in variables to a provided copy of the State object.
|
|
* (i.e. oldState and newState should be equal when passed in.)
|
|
* Both State objects represent only a subset of the total set of variables,
|
|
* with this subset being defined by the mapping varMap.
|
|
* Only variables in this subset are updated.
|
|
* But if doing so requires old values for variables outside the subset, this will cause an exception.
|
|
* It is assumed that any constants have already been defined.
|
|
* @param oldState Variable values in current state
|
|
* @param newState State object to apply changes to
|
|
* @param varMap A mapping from indices (over all variables) to the subset (-1 if not in subset).
|
|
*/
|
|
public void updatePartially(State oldState, State newState, int[] varMap) throws PrismLangException
|
|
{
|
|
int i, j, n;
|
|
n = exprs.size();
|
|
for (i = 0; i < n; i++) {
|
|
j = varMap[getVarIndex(i)];
|
|
if (j != -1) {
|
|
newState.setValue(j, getExpression(i).evaluate(new EvaluateContextSubstate(oldState, varMap)));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check whether this update (from a particular state) would cause any errors, mainly variable overflows.
|
|
* Variable ranges are specified in the passed in VarList.
|
|
* Throws an exception if such an error occurs.
|
|
*/
|
|
public State checkUpdate(State oldState, VarList varList) throws PrismLangException
|
|
{
|
|
int i, n, valNew;
|
|
State res;
|
|
res = new State(oldState);
|
|
n = exprs.size();
|
|
for (i = 0; i < n; i++) {
|
|
valNew = varList.encodeToInt(i, getExpression(i).evaluate(oldState));
|
|
if (valNew < varList.getLow(i) || valNew > varList.getHigh(i))
|
|
throw new PrismLangException("Value of variable " + getVar(i) + " overflows", getExpression(i));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
// Methods required for ASTElement:
|
|
|
|
/**
|
|
* Visitor method.
|
|
*/
|
|
public Object accept(ASTVisitor v) throws PrismLangException
|
|
{
|
|
return v.visit(this);
|
|
}
|
|
|
|
/**
|
|
* Convert to string.
|
|
*/
|
|
public String toString()
|
|
{
|
|
int i, n;
|
|
String s = "";
|
|
|
|
n = exprs.size();
|
|
// normal case
|
|
if (n > 0) {
|
|
for (i = 0; i < n - 1; i++) {
|
|
s = s + "(" + vars.get(i) + "'=" + exprs.get(i) + ") & ";
|
|
}
|
|
s = s + "(" + vars.get(n - 1) + "'=" + exprs.get(n - 1) + ")";
|
|
}
|
|
// special (empty) case
|
|
else {
|
|
s = "true";
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* Perform a deep copy.
|
|
*/
|
|
public ASTElement deepCopy()
|
|
{
|
|
int i, n;
|
|
Update ret = new Update();
|
|
n = getNumElements();
|
|
for (i = 0; i < n; i++) {
|
|
ret.addElement((ExpressionIdent) getVarIdent(i).deepCopy(), getExpression(i).deepCopy());
|
|
ret.setType(i, getType(i));
|
|
ret.setVarIndex(i, getVarIndex(i));
|
|
}
|
|
ret.setPosition(this);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|