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.
1042 lines
25 KiB
1042 lines
25 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.*;
|
|
|
|
import parser.*;
|
|
import parser.visitor.*;
|
|
import prism.PrismLangException;
|
|
import prism.ModelType;
|
|
import parser.type.*;
|
|
|
|
// Class representing parsed model file
|
|
|
|
public class ModulesFile extends ASTElement
|
|
{
|
|
// Model type (enum)
|
|
private ModelType modelType;
|
|
|
|
// Model components
|
|
private FormulaList formulaList;
|
|
private LabelList labelList;
|
|
private ConstantList constantList;
|
|
private Vector<Declaration> globals; // Global variables
|
|
private Vector<Object> modules; // Modules (includes renamed modules)
|
|
private SystemDefn systemDefn; // System definition (system...endsystem construct)
|
|
private ArrayList<RewardStruct> rewardStructs; // Rewards structures
|
|
private Expression initStates; // Initial states specification
|
|
|
|
// Lists of all identifiers used
|
|
private Vector<String> formulaIdents;
|
|
private Vector<String> constantIdents;
|
|
private Vector<String> varIdents; // TODO: don't need?
|
|
// List of all module names
|
|
private String[] moduleNames;
|
|
// List of synchronising actions
|
|
private Vector<String> synchs;
|
|
// Lists of variable info (declaration, name, type)
|
|
private Vector<Declaration> varDecls;
|
|
private Vector<String> varNames;
|
|
private Vector<Type> varTypes;
|
|
|
|
// actual values of (some or all) constants
|
|
private Values constantValues;
|
|
|
|
// Constructor
|
|
|
|
public ModulesFile()
|
|
{
|
|
formulaList = new FormulaList();
|
|
labelList = new LabelList();
|
|
constantList = new ConstantList();
|
|
modelType = ModelType.MDP; // default type
|
|
globals = new Vector<Declaration>();
|
|
modules = new Vector<Object>();
|
|
systemDefn = null;
|
|
rewardStructs = new ArrayList<RewardStruct>();
|
|
initStates = null;
|
|
formulaIdents = new Vector<String>();
|
|
constantIdents = new Vector<String>();
|
|
varIdents = new Vector<String>();
|
|
varDecls = new Vector<Declaration>();
|
|
varNames = new Vector<String>();
|
|
varTypes = new Vector<Type>();
|
|
constantValues = null;
|
|
}
|
|
|
|
// Set methods
|
|
|
|
public void setFormulaList(FormulaList fl)
|
|
{
|
|
formulaList = fl;
|
|
}
|
|
|
|
public void setLabelList(LabelList ll)
|
|
{
|
|
labelList = ll;
|
|
}
|
|
|
|
public void setConstantList(ConstantList cl)
|
|
{
|
|
constantList = cl;
|
|
}
|
|
|
|
public void setModelType(ModelType t)
|
|
{
|
|
modelType = t;
|
|
}
|
|
|
|
public void addGlobal(Declaration d)
|
|
{
|
|
globals.add(d);
|
|
}
|
|
|
|
public void setGlobal(int i, Declaration d)
|
|
{
|
|
globals.set(i, d);
|
|
}
|
|
|
|
public void addModule(Module m)
|
|
{
|
|
modules.add(m);
|
|
m.setParent(this);
|
|
}
|
|
|
|
public void setModule(int i, Module m)
|
|
{
|
|
modules.set(i, m);
|
|
m.setParent(this);
|
|
}
|
|
|
|
public void addRenamedModule(RenamedModule m)
|
|
{
|
|
modules.add(m);
|
|
}
|
|
|
|
public void setSystemDefn(SystemDefn s)
|
|
{
|
|
systemDefn = s;
|
|
}
|
|
|
|
public void clearRewardStructs()
|
|
{
|
|
rewardStructs.clear();
|
|
}
|
|
|
|
public void addRewardStruct(RewardStruct r)
|
|
{
|
|
rewardStructs.add(r);
|
|
}
|
|
|
|
public void setRewardStruct(int i, RewardStruct r)
|
|
{
|
|
rewardStructs.set(i, 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;
|
|
}
|
|
|
|
// Get methods
|
|
|
|
public FormulaList getFormulaList()
|
|
{
|
|
return formulaList;
|
|
}
|
|
|
|
public LabelList getLabelList()
|
|
{
|
|
return labelList;
|
|
}
|
|
|
|
public ConstantList getConstantList()
|
|
{
|
|
return constantList;
|
|
}
|
|
|
|
public ModelType getModelType()
|
|
{
|
|
return modelType;
|
|
}
|
|
|
|
public String getTypeString()
|
|
{
|
|
return "" + modelType;
|
|
}
|
|
|
|
public String getTypeFullString()
|
|
{
|
|
return modelType.fullName();
|
|
}
|
|
|
|
public int getNumGlobals()
|
|
{
|
|
return globals.size();
|
|
}
|
|
|
|
public Declaration getGlobal(int i)
|
|
{
|
|
return 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;
|
|
}
|
|
|
|
/**
|
|
* Get the number of reward structures in the model.
|
|
*/
|
|
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).
|
|
* Returns null if index is out of range.
|
|
*/
|
|
public RewardStruct getRewardStruct(int i)
|
|
{
|
|
return (i < rewardStructs.size()) ? rewardStructs.get(i) : null;
|
|
}
|
|
|
|
/**
|
|
* Get access to the list of reward structures
|
|
*/
|
|
public List<RewardStruct> getRewardStructs()
|
|
{
|
|
return rewardStructs;
|
|
}
|
|
|
|
/**
|
|
* Get the index of a module by its name
|
|
* (indexed from 0, not from 1 like at the user (property language) level).
|
|
* Returns -1 if name does not exist.
|
|
*/
|
|
public int getRewardStructIndex(String name)
|
|
{
|
|
int i, n;
|
|
n = rewardStructs.size();
|
|
for (i = 0; i < n; i++) {
|
|
if ((rewardStructs.get(i)).getName().equals(name))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Get a reward structure by its name
|
|
* Returns null if name does not exist.
|
|
*/
|
|
public RewardStruct getRewardStructByName(String name)
|
|
{
|
|
int i = getRewardStructIndex(name);
|
|
return i == -1 ? null : getRewardStruct(i);
|
|
}
|
|
|
|
/**
|
|
* Get the first reward structure (exists for backwards compatibility only).
|
|
*/
|
|
public RewardStruct getRewardStruct()
|
|
{
|
|
return getRewardStruct(0);
|
|
}
|
|
|
|
/**
|
|
* Get the expression used in init...endinit to define the initial states of the model.
|
|
* This is null if absent, i.e. the model has a single initial state defined by the
|
|
* initial values for each individual variable.
|
|
* If non-null, we have to assume that there may be multiple initial states.
|
|
*/
|
|
public Expression getInitialStates()
|
|
{
|
|
return initStates;
|
|
}
|
|
|
|
/**
|
|
* Look up a property by name.
|
|
* Returns null if not found.
|
|
* Currently only exists for forwards compatibility.
|
|
*/
|
|
public Property getPropertyByName(String name)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check if an identifier is used by this model
|
|
* (as a formula, constant, or variable)
|
|
*/
|
|
public boolean isIdentUsed(String ident)
|
|
{
|
|
return formulaIdents.contains(ident) || constantIdents.contains(ident) || varIdents.contains(ident);
|
|
}
|
|
|
|
// get individual module name
|
|
public String getModuleName(int i)
|
|
{
|
|
return moduleNames[i];
|
|
}
|
|
|
|
// get array of all module names
|
|
public String[] getModuleNames()
|
|
{
|
|
return moduleNames;
|
|
}
|
|
|
|
/**
|
|
* Get the list of action names.
|
|
*/
|
|
public Vector<String> getSynchs()
|
|
{
|
|
return synchs;
|
|
}
|
|
|
|
/**
|
|
* Get the {@code i}th action name (0-indexed).
|
|
*/
|
|
public String getSynch(int i)
|
|
{
|
|
return synchs.get(i);
|
|
}
|
|
|
|
public boolean isSynch(String s)
|
|
{
|
|
if (synchs == null)
|
|
return false;
|
|
else
|
|
return synchs.contains(s);
|
|
}
|
|
|
|
// Variable query methods
|
|
|
|
/**
|
|
* Get the total number of variables (global and local).
|
|
*/
|
|
public int getNumVars()
|
|
{
|
|
return varNames.size();
|
|
}
|
|
|
|
/**
|
|
* Look up the index of a variable in the model by name.
|
|
* Returns -1 if there is no such variable.
|
|
*/
|
|
public int getVarIndex(String name)
|
|
{
|
|
return varNames.indexOf(name);
|
|
}
|
|
|
|
/**
|
|
* Get the declaration of the ith variable.
|
|
*/
|
|
public Declaration getVarDeclaration(int i)
|
|
{
|
|
return varDecls.get(i);
|
|
}
|
|
|
|
/**
|
|
* Get the name of the ith variable.
|
|
*/
|
|
public String getVarName(int i)
|
|
{
|
|
return varNames.get(i);
|
|
}
|
|
|
|
/**
|
|
* Get the type of the ith variable.
|
|
*/
|
|
public Type getVarType(int i)
|
|
{
|
|
return varTypes.get(i);
|
|
}
|
|
|
|
public Vector<String> getVarNames()
|
|
{
|
|
return varNames;
|
|
}
|
|
|
|
public Vector<Type> 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" after parsing (must be called)
|
|
* (do some checks and extract some information)
|
|
*/
|
|
public void tidyUp() throws PrismLangException
|
|
{
|
|
// Clear lists that will generated by this method
|
|
// (in case it has already been called previously).
|
|
formulaIdents.clear();
|
|
constantIdents.clear();
|
|
varIdents.clear();
|
|
varDecls.clear();
|
|
varNames.clear();
|
|
varTypes.clear();
|
|
|
|
// Expansion of formulas and renaming
|
|
|
|
// Check formula identifiers
|
|
checkFormulaIdents();
|
|
// Find all formulas (i.e. locate identifiers which are formulas).
|
|
// Note: This should all be done before replacing any other identifiers
|
|
// (e.g. with variables) because this relies on module renaming which in turn
|
|
// must be done after formula expansion. Then, check for any cyclic
|
|
// dependencies in the formula list and then expand all formulas.
|
|
findAllFormulas(formulaList);
|
|
formulaList.findCycles();
|
|
expandFormulas(formulaList);
|
|
// Perform module renaming
|
|
sortRenamings();
|
|
|
|
// Check label identifiers
|
|
checkLabelIdents();
|
|
|
|
// Check module names
|
|
checkModuleNames();
|
|
|
|
// Get synchronising action names
|
|
getSynchNames();
|
|
// Then identify/check any references to action names
|
|
findAllActions(synchs);
|
|
|
|
// Check constant identifiers
|
|
checkConstantIdents();
|
|
// Find all instances of constants
|
|
// (i.e. locate identifiers which are constants)
|
|
findAllConstants(constantList);
|
|
// Check constants for cyclic dependencies
|
|
constantList.findCycles();
|
|
|
|
// Check variable names, etc.
|
|
checkVarNames();
|
|
// Find all instances of variables, replace identifiers with variables.
|
|
// Also check variables valid, store indices, etc.
|
|
findAllVars(varNames, varTypes);
|
|
|
|
// Find all instances of property refs
|
|
findAllProps(this, null);
|
|
|
|
// Check reward structure names
|
|
checkRewardStructNames();
|
|
|
|
// Various semantic checks
|
|
semanticCheck(this);
|
|
|
|
// Type checking
|
|
typeCheck();
|
|
// If there are no undefined constants, set up values for constants
|
|
// (to avoid need for a later call to setUndefinedConstants).
|
|
// NB: Can't call setUndefinedConstants if there are undefined constants
|
|
// because semanticCheckAfterConstants may fail.
|
|
if (getUndefinedConstants().isEmpty()) {
|
|
setUndefinedConstants(null);
|
|
}
|
|
}
|
|
|
|
// Check formula identifiers
|
|
|
|
private void checkFormulaIdents() throws PrismLangException
|
|
{
|
|
int i, n;
|
|
String s;
|
|
|
|
n = formulaList.size();
|
|
for (i = 0; i < n; i++) {
|
|
s = formulaList.getFormulaName(i);
|
|
if (isIdentUsed(s)) {
|
|
throw new PrismLangException("Duplicated identifier \"" + s + "\"", formulaList.getFormulaNameIdent(i));
|
|
} else {
|
|
formulaIdents.add(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
// sort out modules defined by renaming
|
|
|
|
private void sortRenamings() throws PrismLangException
|
|
{
|
|
int i, j, n, i2, n2;
|
|
RenamedModule module;
|
|
Module newModule;
|
|
String s;
|
|
Object o;
|
|
HashSet<String> renamedSoFar;
|
|
|
|
// Go through 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 renamed module \"" + module.getName() + "\"";
|
|
throw new PrismLangException(s, module.getBaseModuleASTElement());
|
|
}
|
|
// Check for invalid renames
|
|
n2 = module.getNumRenames();
|
|
renamedSoFar = new HashSet<String>();
|
|
for (i2 = 0; i2 < n2; i2++) {
|
|
s = module.getOldName(i2);
|
|
if (!renamedSoFar.add(s)) {
|
|
throw new PrismLangException("Identifier \"" + s + "\" is renamed more than once in module \""
|
|
+ module.getName() + "\"", module.getOldNameASTElement(i2));
|
|
}
|
|
if (formulaList.getFormulaIndex(s) != -1) {
|
|
throw new PrismLangException("Formula \"" + s
|
|
+ "\" cannot be renamed since formulas are expanded before module renaming", module
|
|
.getOldNameASTElement(i2));
|
|
}
|
|
}
|
|
// Then rename (a copy of) base module and replace
|
|
// (note: also store name of base module for later reference)
|
|
newModule = (Module) getModule(j).deepCopy().rename(module);
|
|
newModule.setNameASTElement(module.getNameASTElement());
|
|
newModule.setBaseModule(module.getBaseModule());
|
|
setModule(i, newModule);
|
|
}
|
|
}
|
|
|
|
// check label identifiers
|
|
|
|
private void checkLabelIdents() throws PrismLangException
|
|
{
|
|
int i, n;
|
|
String s;
|
|
Vector<String> labelIdents;
|
|
|
|
// go thru labels
|
|
n = labelList.size();
|
|
labelIdents = new Vector<String>();
|
|
for (i = 0; i < n; i++) {
|
|
s = labelList.getLabelName(i);
|
|
// see if ident has been used already for a label
|
|
if (labelIdents.contains(s)) {
|
|
throw new PrismLangException("Duplicated label name \"" + s + "\"", labelList.getLabelNameIdent(i));
|
|
} else {
|
|
labelIdents.add(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check module names
|
|
|
|
private void checkModuleNames() throws PrismLangException
|
|
{
|
|
int i, j, n;
|
|
String s;
|
|
|
|
// check we have at least one module
|
|
n = modules.size();
|
|
if (n == 0) {
|
|
throw new PrismLangException("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 PrismLangException("Duplicated module name \"" + s + "\"", getModule(i)
|
|
.getNameASTElement());
|
|
}
|
|
}
|
|
moduleNames[i] = s;
|
|
}
|
|
}
|
|
|
|
// get all synch names
|
|
|
|
private void getSynchNames() throws PrismLangException
|
|
{
|
|
Vector<String> v;
|
|
String s;
|
|
int i, j, n, m;
|
|
|
|
// create vector to store names
|
|
synchs = new Vector<String>();
|
|
|
|
// 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 = v.elementAt(j);
|
|
if (!synchs.contains(s)) {
|
|
synchs.add(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
// then extract any which are introduced in system construct (i.e. by
|
|
// renaming)
|
|
if (systemDefn != null) {
|
|
systemDefn.getSynchs(synchs);
|
|
}
|
|
}
|
|
|
|
// check constant identifiers
|
|
|
|
private void checkConstantIdents() throws PrismLangException
|
|
{
|
|
int i, n;
|
|
String s;
|
|
|
|
n = constantList.size();
|
|
for (i = 0; i < n; i++) {
|
|
s = constantList.getConstantName(i);
|
|
if (isIdentUsed(s)) {
|
|
throw new PrismLangException("Duplicated identifier \"" + s + "\"", constantList
|
|
.getConstantNameIdent(i));
|
|
} else {
|
|
constantIdents.add(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check variable names
|
|
|
|
private void checkVarNames() throws PrismLangException
|
|
{
|
|
int i, j, n, m;
|
|
Module module;
|
|
String s;
|
|
|
|
// compile list of all var names
|
|
// and check as we go through
|
|
|
|
// globals
|
|
n = getNumGlobals();
|
|
for (i = 0; i < n; i++) {
|
|
s = getGlobal(i).getName();
|
|
if (isIdentUsed(s)) {
|
|
throw new PrismLangException("Duplicated identifier \"" + s + "\"", getGlobal(i));
|
|
} else {
|
|
varIdents.add(s);
|
|
varDecls.add(getGlobal(i));
|
|
varNames.add(s);
|
|
varTypes.add(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 (isIdentUsed(s)) {
|
|
throw new PrismLangException("Duplicated identifier \"" + s + "\"", module.getDeclaration(j));
|
|
} else {
|
|
varIdents.add(s);
|
|
varDecls.add(module.getDeclaration(j));
|
|
varNames.add(s);
|
|
varTypes.add(module.getDeclaration(j).getType());
|
|
}
|
|
}
|
|
}
|
|
|
|
// check there is at least one variable
|
|
if (varNames.size() == 0) {
|
|
throw new PrismLangException("There must be at least one variable");
|
|
}
|
|
}
|
|
|
|
// Check there are no duplicate names labelling reward structs
|
|
|
|
private void checkRewardStructNames() throws PrismLangException
|
|
{
|
|
int i, n;
|
|
String s;
|
|
HashSet<String> names = new HashSet<String>();
|
|
n = getNumRewardStructs();
|
|
for (i = 0; i < n; i++) {
|
|
s = getRewardStruct(i).getName();
|
|
if (s != null && !"".equals(s))
|
|
if (!names.add(s))
|
|
throw new PrismLangException("Duplicated reward structure name \"" + s + "\"", getRewardStruct(i));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a list of constants in the model that are undefined
|
|
* ("const int x;" rather than "const int x = 1;")
|
|
*/
|
|
public Vector<String> getUndefinedConstants()
|
|
{
|
|
return constantList.getUndefinedConstants();
|
|
}
|
|
|
|
/**
|
|
* Set values for *all* undefined constants and then evaluate all constants.
|
|
* If there are no undefined constants, {@code someValues} can be null.
|
|
* Undefined constants can be subsequently redefined to different values with the same method.
|
|
* The current constant values (if set) are available via {@link #getConstantValues()}.
|
|
* Calling this method also triggers some additional semantic checks
|
|
* that can only be done once constant values have been specified.
|
|
*/
|
|
public void setUndefinedConstants(Values someValues) throws PrismLangException
|
|
{
|
|
constantValues = constantList.evaluateConstants(someValues, null);
|
|
semanticCheckAfterConstants(this, null);
|
|
}
|
|
|
|
/**
|
|
* Check if {@code name} is a *defined* constant in the model,
|
|
* i.e. a constant whose value was *not* left unspecified.
|
|
*/
|
|
public boolean isDefinedConstant(String name)
|
|
{
|
|
return constantList.isDefinedConstant(name);
|
|
}
|
|
|
|
/**
|
|
* Get access to the values for all constants in the model, including the
|
|
* undefined constants set previously via the method {@link #setUndefinedConstants(Values)}.
|
|
* Until they are set for the first time, this method returns null.
|
|
*/
|
|
public Values getConstantValues()
|
|
{
|
|
return constantValues;
|
|
}
|
|
|
|
/**
|
|
* Create a State object representing the default initial state of this model.
|
|
* If there are potentially multiple initial states (because the model has an
|
|
* init...endinit specification), this method returns null;
|
|
* Assumes that values for constants have been provided for the model.
|
|
* Note: This method replaces the old getInitialValues() method,
|
|
* since State objects are now preferred to Values objects for efficiency.
|
|
*/
|
|
public State getDefaultInitialState() throws PrismLangException
|
|
{
|
|
int i, j, count, n, n2;
|
|
Module module;
|
|
Declaration decl;
|
|
State initialState;
|
|
Object initialValue;
|
|
|
|
if (initStates != null) {
|
|
return null;
|
|
}
|
|
|
|
// Create State object
|
|
initialState = new State(getNumVars());
|
|
// Then add values for all globals and all locals, in that order
|
|
count = 0;
|
|
n = getNumGlobals();
|
|
for (i = 0; i < n; i++) {
|
|
decl = getGlobal(i);
|
|
initialValue = decl.getStartOrDefault().evaluate(constantValues);
|
|
initialValue = getGlobal(i).getType().castValueTo(initialValue);
|
|
initialState.setValue(count++, initialValue);
|
|
}
|
|
n = getNumModules();
|
|
for (i = 0; i < n; i++) {
|
|
module = getModule(i);
|
|
n2 = module.getNumDeclarations();
|
|
for (j = 0; j < n2; j++) {
|
|
decl = module.getDeclaration(j);
|
|
initialValue = decl.getStartOrDefault().evaluate(constantValues);
|
|
initialValue = module.getDeclaration(j).getType().castValueTo(initialValue);
|
|
initialState.setValue(count++, initialValue);
|
|
}
|
|
}
|
|
|
|
return initialState;
|
|
}
|
|
|
|
/**
|
|
* Create a Values object representing the default initial state of this model.
|
|
* Deprecated: Use getDefaultInitialState() instead
|
|
* (or new Values(getDefaultInitialState(), modulesFile)).
|
|
*/
|
|
public Values getInitialValues() throws PrismLangException
|
|
{
|
|
int i, j, n, n2;
|
|
Module module;
|
|
Declaration decl;
|
|
Values values;
|
|
Object initialValue;
|
|
|
|
if (initStates != null) {
|
|
throw new PrismLangException("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);
|
|
initialValue = decl.getStartOrDefault().evaluate(constantValues);
|
|
initialValue = getGlobal(i).getType().castValueTo(initialValue);
|
|
values.addValue(decl.getName(), initialValue);
|
|
}
|
|
// 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);
|
|
initialValue = decl.getStartOrDefault().evaluate(constantValues);
|
|
initialValue = module.getDeclaration(j).getType().castValueTo(initialValue);
|
|
values.addValue(decl.getName(), initialValue);
|
|
}
|
|
}
|
|
|
|
return values;
|
|
}
|
|
|
|
/**
|
|
* Recompute all information about variables.
|
|
* More precisely... TODO
|
|
* Note: This does not re-compute the list of all identifiers used.
|
|
*/
|
|
public void recomputeVariableinformation() throws PrismLangException
|
|
{
|
|
int i, n;
|
|
|
|
// Recompute lists of all variables and types
|
|
varDecls = new Vector<Declaration>();
|
|
varNames = new Vector<String>();
|
|
varTypes = new Vector<Type>();
|
|
// Globals
|
|
for (Declaration decl : globals) {
|
|
varDecls.add(decl);
|
|
varNames.add(decl.getName());
|
|
varTypes.add(decl.getType());
|
|
}
|
|
// Locals
|
|
n = modules.size();
|
|
for (i = 0; i < n; i++) {
|
|
for (Declaration decl : getModule(i).getDeclarations()) {
|
|
varDecls.add(decl);
|
|
varNames.add(decl.getName());
|
|
varTypes.add(decl.getType());
|
|
}
|
|
}
|
|
// Find all instances of variables, replace identifiers with variables.
|
|
// Also check variables valid, store indices, etc.
|
|
findAllVars(varNames, varTypes);
|
|
}
|
|
|
|
/**
|
|
* Create a VarList object storing information about all variables in this model.
|
|
* Assumes that values for constants have been provided for the model.
|
|
* Also performs various syntactic checks on the variables.
|
|
*/
|
|
public VarList createVarList() throws PrismLangException
|
|
{
|
|
return new VarList(this);
|
|
}
|
|
|
|
// Methods required for ASTElement:
|
|
|
|
/**
|
|
* Visitor method.
|
|
*/
|
|
public Object accept(ASTVisitor v) throws PrismLangException
|
|
{
|
|
return v.visit(this);
|
|
}
|
|
|
|
/**
|
|
* Convert to string.
|
|
*/
|
|
public String toString()
|
|
{
|
|
String s = "", tmp;
|
|
int i, n;
|
|
|
|
s += modelType.toString().toLowerCase() + "\n\n";
|
|
|
|
tmp = "" + formulaList;
|
|
if (tmp.length() > 0)
|
|
tmp += "\n";
|
|
s += tmp;
|
|
|
|
tmp = "" + labelList;
|
|
if (tmp.length() > 0)
|
|
tmp += "\n";
|
|
s += tmp;
|
|
|
|
tmp = "" + constantList;
|
|
if (tmp.length() > 0)
|
|
tmp += "\n";
|
|
s += tmp;
|
|
|
|
n = getNumGlobals();
|
|
for (i = 0; i < n; i++) {
|
|
s += "global " + getGlobal(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 = getNumRewardStructs();
|
|
for (i = 0; i < n; i++) {
|
|
s += "\n" + getRewardStruct(i);
|
|
}
|
|
|
|
if (initStates != null) {
|
|
s += "\n" + "init " + initStates + " endinit\n";
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* Perform a deep copy.
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
public ASTElement deepCopy()
|
|
{
|
|
int i, n;
|
|
ModulesFile ret = new ModulesFile();
|
|
|
|
// Copy ASTElement stuff
|
|
ret.setPosition(this);
|
|
// Copy type
|
|
ret.setModelType(modelType);
|
|
// Deep copy main components
|
|
ret.setFormulaList((FormulaList) formulaList.deepCopy());
|
|
ret.setLabelList((LabelList) labelList.deepCopy());
|
|
ret.setConstantList((ConstantList) constantList.deepCopy());
|
|
n = getNumGlobals();
|
|
for (i = 0; i < n; i++) {
|
|
ret.addGlobal((Declaration) getGlobal(i).deepCopy());
|
|
}
|
|
n = getNumModules();
|
|
for (i = 0; i < n; i++) {
|
|
ret.addModule((Module) getModule(i).deepCopy());
|
|
}
|
|
if (systemDefn != null)
|
|
ret.setSystemDefn(systemDefn.deepCopy());
|
|
n = getNumRewardStructs();
|
|
for (i = 0; i < n; i++) {
|
|
ret.addRewardStruct((RewardStruct) getRewardStruct(i).deepCopy());
|
|
}
|
|
if (initStates != null)
|
|
ret.setInitialStates(initStates.deepCopy());
|
|
// Copy other (generated) info
|
|
ret.formulaIdents = (formulaIdents == null) ? null : (Vector<String>)formulaIdents.clone();
|
|
ret.constantIdents = (constantIdents == null) ? null : (Vector<String>)constantIdents.clone();
|
|
ret.varIdents = (varIdents == null) ? null : (Vector<String>)varIdents.clone();
|
|
ret.moduleNames = (moduleNames == null) ? null : moduleNames.clone();
|
|
ret.synchs = (synchs == null) ? null : (Vector<String>)synchs.clone();
|
|
if (varDecls != null) {
|
|
ret.varDecls = new Vector<Declaration>();
|
|
for (Declaration d : varDecls)
|
|
ret.varDecls.add((Declaration) d.deepCopy());
|
|
}
|
|
ret.varNames = (varNames == null) ? null : (Vector<String>)varNames.clone();
|
|
ret.varTypes = (varTypes == null) ? null : (Vector<Type>)varTypes.clone();
|
|
ret.constantValues = (constantValues == null) ? null : new Values(constantValues);
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|