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.
846 lines
22 KiB
846 lines
22 KiB
//==============================================================================
|
|
//
|
|
// Copyright (c) 2002-
|
|
// Authors:
|
|
// * Dave Parker <dxp@cs.bham.uc.uk> (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;
|
|
|
|
import java.util.*;
|
|
|
|
import prism.PrismException;
|
|
|
|
// class to store representation of parsed modules file
|
|
|
|
public class ModulesFile
|
|
{
|
|
// constants for types of system
|
|
public static final int PROBABILISTIC = 1;
|
|
public static final int NONDETERMINISTIC = 2;
|
|
public static final int STOCHASTIC = 3;
|
|
public static final String typeStrings[] = {"?", "Probabilistic (DTMC)", "Nondeterministic (MDP)", "Stochastic (CTMC)"};
|
|
|
|
// formulas (macros)
|
|
private FormulaList formulaList;
|
|
|
|
// constants
|
|
private ConstantList constantList;
|
|
|
|
// basic components
|
|
private int type; // type: prob/nondet/stoch
|
|
private Vector globals; // global variables
|
|
private Vector modules; // modules (includes renamed modules)
|
|
private SystemDefn systemDefn; // system definition (process algebraic)
|
|
private ArrayList rewardStructs; // rewards structures
|
|
private Expression initStates; // set of initial states
|
|
|
|
// identifiers/etc.
|
|
private Vector allIdentsUsed;
|
|
private String[] moduleNames;
|
|
private Vector synchs;
|
|
private Vector varNames;
|
|
private Vector varTypes;
|
|
|
|
// actual values of constants
|
|
private Values constantValues;
|
|
|
|
// constructor
|
|
|
|
public ModulesFile()
|
|
{
|
|
// initialise
|
|
formulaList = new FormulaList(); // empty - will be overwritten
|
|
constantList = new ConstantList(); // empty - will be overwritten
|
|
type = NONDETERMINISTIC; // default type
|
|
globals = new Vector();
|
|
modules = new Vector();
|
|
systemDefn = null;
|
|
rewardStructs = new ArrayList();
|
|
initStates = null;
|
|
allIdentsUsed = new Vector();
|
|
varNames = new Vector();
|
|
varTypes = new Vector();
|
|
constantValues = null;
|
|
}
|
|
|
|
// set up methods - these are called by the parser to create a ModulesFile object
|
|
|
|
public void setFormulaList(FormulaList fl) { formulaList = fl; }
|
|
|
|
public void setConstantList(ConstantList cl) { constantList = cl; }
|
|
|
|
public void setType(int t) { type = t; }
|
|
|
|
public void addGlobal(Declaration d) { globals.addElement(d); }
|
|
|
|
public void addModule(Module m) { modules.addElement(m); m.setParent(this); }
|
|
|
|
public void addRenamedModule(RenamedModule m) { modules.addElement(m); }
|
|
|
|
public void setSystemDefn(SystemDefn s) { systemDefn = s; }
|
|
|
|
public void addRewardStruct(RewardStruct r) { rewardStructs.add(r); }
|
|
|
|
// this method is included for backwards compatibility only
|
|
public void setRewardStruct(RewardStruct r) { rewardStructs.clear(); rewardStructs.add(r); }
|
|
|
|
public void setInitialStates(Expression e) { initStates = e; }
|
|
|
|
// accessor methods
|
|
|
|
public FormulaList getFormulaList() { return formulaList; }
|
|
|
|
public ConstantList getConstantList() { return constantList; }
|
|
|
|
public int getType() { return type; }
|
|
|
|
public String getTypeString() { return typeStrings[type]; }
|
|
|
|
public int getNumGlobals() { return globals.size(); }
|
|
|
|
public Declaration getGlobal(int i) { return (Declaration)globals.elementAt(i); }
|
|
|
|
public int getNumModules() { return modules.size(); }
|
|
|
|
// get module by index
|
|
// returns null if it is a RenamedModule
|
|
// these will have been replaced with Modules after tidyUp()
|
|
public Module getModule(int i)
|
|
{
|
|
Object o = modules.elementAt(i);
|
|
return (o instanceof Module) ? (Module)o : null;
|
|
}
|
|
|
|
// get the index of a module by its name
|
|
// (returns -1 if it does not exist)
|
|
// (or is a RenamedModule and hasn't been turned into a normal Module yet)
|
|
public int getModuleIndex(String s)
|
|
{
|
|
int i;
|
|
Module m;
|
|
|
|
for (i = 0; i < modules.size(); i++) {
|
|
m = getModule(i);
|
|
if (m != null) if (s.equals(m.getName())) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public SystemDefn getSystemDefn() { return systemDefn; }
|
|
|
|
public int getNumRewardStructs() { return rewardStructs.size(); }
|
|
|
|
// Get a reward structure by its index
|
|
// (indexed from 0, not from 1 like at the user (property language) level)
|
|
|
|
public RewardStruct getRewardStruct(int i) { return (i<rewardStructs.size()) ? (RewardStruct)rewardStructs.get(i) : null; }
|
|
|
|
// Get the index of a module by its name
|
|
// (indexed from 0, not from 1 like at the user (property language) level)
|
|
|
|
public int getRewardStructIndex(String name)
|
|
{
|
|
int i, n;
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
if (((RewardStruct)rewardStructs.get(i)).getName().equals(name)) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// this method is included for backwards compatibility only
|
|
public RewardStruct getRewardStruct() { return (rewardStructs.size()>0) ? (RewardStruct)rewardStructs.get(0) : null; }
|
|
|
|
public Expression getInitialStates() { return initStates; }
|
|
|
|
public Vector getAllIdentsUsed() { return allIdentsUsed; }
|
|
|
|
// get individual module name
|
|
public String getModuleName(int i) { return moduleNames[i]; }
|
|
|
|
// get array of all module names
|
|
public String[] getModuleNames() { return moduleNames; }
|
|
|
|
public Vector getSynchs() { return synchs; }
|
|
|
|
public Vector getVarNames() { return varNames; }
|
|
|
|
public Vector getVarTypes() { return varTypes; }
|
|
|
|
public boolean isGlobalVariable(String s)
|
|
{
|
|
int i, n;
|
|
|
|
n = getNumGlobals();
|
|
for (i = 0; i < n; i++) {
|
|
if (getGlobal(i).getName().equals(s)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// method to tidy up
|
|
// (called after parsing to do some checks and extract some information)
|
|
|
|
public void tidyUp() throws PrismException
|
|
{
|
|
// check formula identifiers
|
|
checkFormulaIdents();
|
|
// find all instances of formulas
|
|
// (i.e. locate idents which are formulas)
|
|
// (n.b. can't determine other idents such as vars at the same time
|
|
// because this relies on module renaming which in turn
|
|
// must be done after formulas have been expanded
|
|
findAllFormulas();
|
|
// check formulas for cyclic dependencies
|
|
formulaList.findCycles();
|
|
// expand any formulas
|
|
expandFormulas();
|
|
|
|
// sort out any modules defined by renaming
|
|
sortRenamings();
|
|
|
|
// check module names
|
|
checkModuleNames();
|
|
|
|
// get synch names
|
|
getSynchNames();
|
|
// check system definition
|
|
checkSystemDefn();
|
|
|
|
// check constant identifiers
|
|
checkConstantIdents();
|
|
// find all instances of constants
|
|
// (i.e. locate idents which are constants)
|
|
findAllConstants();
|
|
// check constants for cyclic dependencies
|
|
constantList.findCycles();
|
|
|
|
// check variable names
|
|
checkVarNames();
|
|
// find all instances of variables
|
|
// (i.e. locate idents which are variables)
|
|
findAllVars();
|
|
|
|
// check reward struct names
|
|
checkRewardStructNames();
|
|
|
|
// check everything is ok
|
|
// (including type checking)
|
|
check();
|
|
}
|
|
|
|
// check formula identifiers
|
|
|
|
private void checkFormulaIdents() throws PrismException
|
|
{
|
|
int i, n;
|
|
String s;
|
|
|
|
n = formulaList.size();
|
|
for (i = 0; i < n; i++) {
|
|
s = formulaList.getFormulaName(i);
|
|
if (allIdentsUsed.contains(s)) {
|
|
throw new PrismException("Duplicated identifier \"" + s + "\"");
|
|
}
|
|
else {
|
|
allIdentsUsed.addElement(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
// find all formulas (i.e. locate idents which are formulas)
|
|
|
|
private void findAllFormulas() throws PrismException
|
|
{
|
|
int i, n;
|
|
Module module;
|
|
|
|
// look in formula list
|
|
formulaList.findAllFormulas();
|
|
// look in constants
|
|
constantList.findAllFormulas(formulaList);
|
|
// look in globals
|
|
n = globals.size();
|
|
for (i = 0; i < n; i++) {
|
|
getGlobal(i).findAllFormulas(formulaList);
|
|
}
|
|
// look in (non-renamed) modules
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
module = getModule(i);
|
|
if (module != null) {
|
|
module.findAllFormulas(formulaList);
|
|
}
|
|
}
|
|
// look in reward structs
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
((RewardStruct)rewardStructs.get(i)).findAllFormulas(formulaList);
|
|
}
|
|
// look in init states (if present)
|
|
if (initStates != null) initStates.findAllFormulas(formulaList);
|
|
}
|
|
|
|
// expand any formulas
|
|
|
|
private void expandFormulas() throws PrismException
|
|
{
|
|
int i, n;
|
|
Module module;
|
|
|
|
// look in formula list
|
|
// (best to do this first - sorts out any linked formulas)
|
|
formulaList.expandFormulas();
|
|
// look in constants
|
|
constantList.expandFormulas(formulaList);
|
|
// look in globals
|
|
n = globals.size();
|
|
for (i = 0; i < n; i++) {
|
|
getGlobal(i).expandFormulas(formulaList);
|
|
}
|
|
// look in (non-renamed) modules
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
module = getModule(i);
|
|
if (module != null) {
|
|
module.expandFormulas(formulaList);
|
|
}
|
|
}
|
|
// look in reward structs
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
((RewardStruct)rewardStructs.get(i)).expandFormulas(formulaList);
|
|
}
|
|
// look in init states (if present)
|
|
if (initStates != null) initStates.expandFormulas(formulaList);
|
|
}
|
|
|
|
// sort out modules defined by renaming
|
|
|
|
private void sortRenamings() throws PrismException
|
|
{
|
|
int i, j, n;
|
|
RenamedModule module;
|
|
Module baseModule, newModule;
|
|
String s;
|
|
Object o;
|
|
|
|
// go thru modules and find ones which are defined by renaming
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
o = modules.elementAt(i);
|
|
if (o instanceof Module) continue;
|
|
module = (RenamedModule)o;
|
|
// check base module exists
|
|
j = getModuleIndex(module.getBaseModule());
|
|
if (j == -1) {
|
|
s = "No such module " + module.getBaseModule();
|
|
s += " in rename \"" + module.getName() + " = ...\"";
|
|
throw new PrismException(s);
|
|
}
|
|
baseModule = getModule(j);
|
|
// then do renaming and replace with new module
|
|
newModule = baseModule.rename(module);
|
|
modules.setElementAt(newModule, i);
|
|
newModule.setParent(this);
|
|
}
|
|
}
|
|
|
|
// check module names
|
|
|
|
private void checkModuleNames() throws PrismException
|
|
{
|
|
int i, j, n;
|
|
String s;
|
|
|
|
// check we have at least one module
|
|
n = modules.size();
|
|
if (n == 0) {
|
|
throw new PrismException("There must be at least one module");
|
|
}
|
|
|
|
// compile list of all module names
|
|
// and check as we go through
|
|
moduleNames = new String[n];
|
|
for (i = 0; i < n; i++) {
|
|
s = getModule(i).getName();
|
|
for (j = 0; j < i; j++) {
|
|
if (s.equals(moduleNames[j])) {
|
|
throw new PrismException("Duplicated module name \"" + s + "\"");
|
|
}
|
|
}
|
|
moduleNames[i] = s;
|
|
}
|
|
}
|
|
|
|
// get all synch names
|
|
|
|
private void getSynchNames() throws PrismException
|
|
{
|
|
Vector v;
|
|
String s;
|
|
int i, j, n, m;
|
|
|
|
// create vector to store names
|
|
synchs = new Vector();
|
|
|
|
// go thru modules and extract names which appear in their commands
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
v = getModule(i).getAllSynchs();
|
|
m = v.size();
|
|
for (j = 0; j < m; j++) {
|
|
s = (String)v.elementAt(j);
|
|
if (!synchs.contains(s)) {
|
|
synchs.addElement(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
// then extract any which are introduced in system construct (i.e. by renaming)
|
|
if (systemDefn != null) {
|
|
systemDefn.getSynchs(synchs);
|
|
}
|
|
}
|
|
|
|
// check system definition (if present)
|
|
|
|
private void checkSystemDefn() throws PrismException
|
|
{
|
|
int i, n;
|
|
Vector v;
|
|
|
|
if (systemDefn != null) {
|
|
|
|
// check that all modules appear exactly once
|
|
systemDefn.getModules(v = new Vector());
|
|
if (v.size() != modules.size()) {
|
|
throw new PrismException("All modules must appear in the \"system\" construct exactly once");
|
|
}
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
if (!(v.contains(getModule(i).getName()))) {
|
|
throw new PrismException("All modules must appear in the \"system\" construct exactly once");
|
|
}
|
|
}
|
|
|
|
// do dome other checks (recursively)
|
|
// nb: need to pass in set of synchronising action names
|
|
systemDefn.check(synchs);
|
|
}
|
|
}
|
|
|
|
// check constant identifiers
|
|
|
|
private void checkConstantIdents() throws PrismException
|
|
{
|
|
int i, n;
|
|
String s;
|
|
|
|
n = constantList.size();
|
|
for (i = 0; i < n; i++) {
|
|
s = constantList.getConstantName(i);
|
|
if (allIdentsUsed.contains(s)) {
|
|
throw new PrismException("Duplicated identifier \"" + s + "\"");
|
|
}
|
|
else {
|
|
allIdentsUsed.addElement(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
// find all constants (i.e. locate idents which are constants)
|
|
|
|
private void findAllConstants() throws PrismException
|
|
{
|
|
int i, n;
|
|
|
|
// look in constants
|
|
constantList.findAllConstants(constantList);
|
|
// look in globals
|
|
n = globals.size();
|
|
for (i = 0; i < n; i++) {
|
|
getGlobal(i).findAllConstants(constantList);
|
|
}
|
|
// look in modules
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
getModule(i).findAllConstants(constantList);
|
|
}
|
|
// look in reward structs
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
((RewardStruct)rewardStructs.get(i)).findAllConstants(constantList);
|
|
}
|
|
// look in init states (if present)
|
|
if (initStates != null) initStates.findAllConstants(constantList);
|
|
}
|
|
|
|
// check variable names
|
|
|
|
private void checkVarNames() throws PrismException
|
|
{
|
|
int i, j, n, m;
|
|
Module module;
|
|
String s;
|
|
|
|
// compile list of all var names
|
|
// and check as we go through
|
|
|
|
// globals
|
|
n = globals.size();
|
|
for (i = 0; i < n; i++) {
|
|
s = getGlobal(i).getName();
|
|
if (allIdentsUsed.contains(s)) {
|
|
throw new PrismException("Duplicated identifier \"" + s + "\"");
|
|
}
|
|
else {
|
|
allIdentsUsed.addElement(s);
|
|
varNames.addElement(s);
|
|
varTypes.addElement(new Integer(getGlobal(i).getType()));
|
|
}
|
|
}
|
|
|
|
// locals
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
module = getModule(i);
|
|
m = module.getNumDeclarations();
|
|
for (j = 0; j < m; j++) {
|
|
s = module.getDeclaration(j).getName();
|
|
if (allIdentsUsed.contains(s)) {
|
|
throw new PrismException("Duplicated identifier \"" + s + "\"");
|
|
}
|
|
else {
|
|
allIdentsUsed.addElement(s);
|
|
varNames.addElement(s);
|
|
varTypes.addElement(new Integer(module.getDeclaration(j).getType()));
|
|
}
|
|
}
|
|
}
|
|
|
|
// check there is at least one variable
|
|
if (varNames.size() == 0) {
|
|
throw new PrismException("There must be at least one variable");
|
|
}
|
|
}
|
|
|
|
// find all variables (i.e. locate idents which are variables)
|
|
|
|
private void findAllVars() throws PrismException
|
|
{
|
|
int i, n;
|
|
|
|
// nb: we even check in places where there shouldn't be vars
|
|
// eg. in constant definitions etc.
|
|
|
|
// look in constants
|
|
constantList.findAllVars(varNames, varTypes);
|
|
// look in globals
|
|
n = globals.size();
|
|
for (i = 0; i < n; i++) {
|
|
getGlobal(i).findAllVars(varNames, varTypes);
|
|
}
|
|
// look in modules
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
getModule(i).findAllVars(varNames, varTypes);
|
|
}
|
|
// look in reward structs
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
((RewardStruct)rewardStructs.get(i)).findAllVars(varNames, varTypes);
|
|
}
|
|
// look in init states (if present)
|
|
if (initStates != null) initStates.findAllVars(varNames, varTypes);
|
|
}
|
|
|
|
// Check there are no duplicate names labelling reward structs
|
|
|
|
private void checkRewardStructNames() throws PrismException
|
|
{
|
|
int i, n;
|
|
String s;
|
|
HashSet names = new HashSet();
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
s = ((RewardStruct)rewardStructs.get(i)).getName();
|
|
if (s != null & !"".equals(s)) if (!names.add(s)) throw new PrismException("Duplicated reward structure name \""+s+"\"");
|
|
}
|
|
}
|
|
|
|
// check everything is ok
|
|
// (includes type checking)
|
|
|
|
private void check() throws PrismException
|
|
{
|
|
int i, j, n, n2;
|
|
Module module;
|
|
Vector v;
|
|
|
|
// check constants
|
|
constantList.check();
|
|
// check globals
|
|
n = globals.size();
|
|
for (i = 0; i < n; i++) {
|
|
getGlobal(i).check();
|
|
}
|
|
// check modules
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
getModule(i).check();
|
|
}
|
|
// look in reward structs
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
((RewardStruct)rewardStructs.get(i)).check();
|
|
}
|
|
// check init states (if present)
|
|
if (initStates != null) {
|
|
// if any of the variables also specify initial values, this is an error
|
|
n = globals.size();
|
|
for (i = 0; i < n; i++) {
|
|
if (getGlobal(i).isStartSpecified()) throw new PrismException("Cannot use both \"init...endinit\" and initial values for variables");
|
|
}
|
|
n = getNumModules();
|
|
for (i = 0; i < n; i++) {
|
|
module = getModule(i);
|
|
n2 = module.getNumDeclarations();
|
|
for (j = 0; j < n2; j++) {
|
|
if (module.getDeclaration(j).isStartSpecified()) throw new PrismException("Cannot use both \"init...endinit\" and initial values for variables");
|
|
}
|
|
}
|
|
// check expression is ok
|
|
initStates.check();
|
|
// type check expressions
|
|
if (initStates.getType() != Expression.BOOLEAN) {
|
|
throw new PrismException("Initial states declaration must be Boolean");
|
|
}
|
|
}
|
|
}
|
|
|
|
// get undefined constants
|
|
|
|
public Vector getUndefinedConstants()
|
|
{
|
|
return constantList.getUndefinedConstants();
|
|
}
|
|
|
|
// set values for undefined constants and evaluate all constants
|
|
// always need to call this, even when there are no undefined constants
|
|
// (if this is the case, someValues can be null)
|
|
|
|
public void setUndefinedConstants(Values someValues) throws PrismException
|
|
{
|
|
constantValues = constantList.evaluateConstants(someValues, null);
|
|
}
|
|
|
|
// get all constant values
|
|
|
|
public Values getConstantValues()
|
|
{
|
|
return constantValues;
|
|
}
|
|
|
|
// create a Values object to represent (a unique) initial state
|
|
|
|
public Values getInitialValues() throws PrismException
|
|
{
|
|
int i, j, n, n2;
|
|
Module module;
|
|
Declaration decl;
|
|
Values values;
|
|
|
|
if (initStates != null) {
|
|
throw new PrismException("There are multiple initial states");
|
|
}
|
|
|
|
// set up variable list
|
|
values = new Values();
|
|
|
|
// first add all globals
|
|
n = getNumGlobals();
|
|
for (i = 0; i < n; i++) {
|
|
decl = getGlobal(i);
|
|
values.addValue(decl.getName(), decl.getStart().evaluate(constantValues, null));
|
|
}
|
|
// then add all module variables
|
|
n = getNumModules();
|
|
for (i = 0; i < n; i++) {
|
|
module = getModule(i);
|
|
n2 = module.getNumDeclarations();
|
|
for (j = 0; j < n2; j++) {
|
|
decl = module.getDeclaration(j);
|
|
values.addValue(decl.getName(), decl.getStart().evaluate(constantValues, null));
|
|
}
|
|
}
|
|
|
|
return values;
|
|
}
|
|
|
|
// extract information about all variables and return in a VarList object
|
|
|
|
public VarList createVarList() throws PrismException
|
|
{
|
|
int i, j, n, n2, low, high, start;
|
|
String name;
|
|
Module module;
|
|
Declaration decl;
|
|
VarList varList;
|
|
|
|
// set up variable list
|
|
varList = new VarList();
|
|
|
|
// first add all globals to the list
|
|
n = getNumGlobals();
|
|
for (i = 0; i < n; i++) {
|
|
decl = getGlobal(i);
|
|
name = decl.getName();
|
|
// check it is not a duplicate
|
|
if (varList.exists(name)) {
|
|
String s = "Duplicated variable " + name;
|
|
throw new PrismException(s);
|
|
}
|
|
// variable is integer
|
|
if (decl.getType() == Expression.INT) {
|
|
low = decl.getLow().evaluateInt(constantValues, null);
|
|
high = decl.getHigh().evaluateInt(constantValues, null);
|
|
start = decl.getStart().evaluateInt(constantValues, null);
|
|
}
|
|
// variable is boolean
|
|
else {
|
|
low = 0;
|
|
high = 1;
|
|
start = (decl.getStart().evaluateBoolean(constantValues, null)) ? 1 : 0;
|
|
}
|
|
// check range is valid
|
|
if (high - low <= 0) {
|
|
String s = "Invalid range (" + low + "-" + high + ") for variable " + name;
|
|
throw new PrismException(s);
|
|
}
|
|
// check start is valid
|
|
if (start < low || start > high) {
|
|
String s = "Invalid initial value (" + start + ") for variable " + name;
|
|
throw new PrismException(s);
|
|
}
|
|
varList.addVar(name, low, high, start, -1, decl.getType());
|
|
}
|
|
|
|
// then add all module variables to the list
|
|
n = getNumModules();
|
|
for (i = 0; i < n; i++) {
|
|
module = getModule(i);
|
|
n2 = module.getNumDeclarations();
|
|
for (j = 0; j < n2; j++) {
|
|
decl = module.getDeclaration(j);
|
|
name = decl.getName();
|
|
// check it is not a duplicate
|
|
if (varList.exists(name)) {
|
|
String s = "Duplicated variable " + name;
|
|
throw new PrismException(s);
|
|
}
|
|
// variable is integer
|
|
if (decl.getType() == Expression.INT) {
|
|
low = decl.getLow().evaluateInt(constantValues, null);
|
|
high = decl.getHigh().evaluateInt(constantValues, null);
|
|
start = decl.getStart().evaluateInt(constantValues, null);
|
|
}
|
|
// variable is boolean
|
|
else {
|
|
low = 0;
|
|
high = 1;
|
|
start = (decl.getStart().evaluateBoolean(constantValues, null)) ? 1 : 0;
|
|
}
|
|
// check range is valid
|
|
if (high - low <= 0) {
|
|
String s = "Invalid range (" + low + "-" + high + ") for variable " + name;
|
|
throw new PrismException(s);
|
|
}
|
|
// check start is valid
|
|
if (start < low || start > high) {
|
|
String s = "Invalid initial value (" + start + ") for variable " + name;
|
|
throw new PrismException(s);
|
|
}
|
|
varList.addVar(name, low, high, start, i, decl.getType());
|
|
}
|
|
}
|
|
|
|
return varList;
|
|
}
|
|
|
|
// convert to string
|
|
|
|
public String toString()
|
|
{
|
|
String s = "", tmp;
|
|
int i, n;
|
|
|
|
switch (type) {
|
|
case PROBABILISTIC: s += "dtmc"; break;
|
|
case NONDETERMINISTIC: s += "mdp"; break;
|
|
case STOCHASTIC: s += "ctmc"; break;
|
|
}
|
|
s += "\n\n";
|
|
|
|
tmp = "" + formulaList;
|
|
if (tmp.length() > 0) tmp += "\n";
|
|
s += tmp;
|
|
|
|
tmp = "" + constantList;
|
|
if (tmp.length() > 0) tmp += "\n";
|
|
s += tmp;
|
|
|
|
n = globals.size();
|
|
for (i = 0; i < n; i++) {
|
|
s += "global " + globals.elementAt(i) + ";\n";
|
|
}
|
|
if (n > 0) {
|
|
s += "\n";
|
|
}
|
|
|
|
for (i = 0; i < modules.size()-1; i++) {
|
|
s += modules.elementAt(i) + "\n\n";
|
|
}
|
|
s += modules.elementAt(modules.size()-1) + "\n";
|
|
|
|
if (systemDefn != null) {
|
|
s += "\nsystem " + systemDefn + " endsystem\n";
|
|
}
|
|
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
s += "\n" + rewardStructs.get(i);
|
|
}
|
|
|
|
if (initStates != null) {
|
|
s += "\n" + "init " + initStates + " endinit";
|
|
}
|
|
|
|
return s;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|