/** Constructor. */ public PTAModelChecker(Prism prism, ModulesFile modulesFile, PropertiesFile propertiesFile) throws PrismException { this.prism = prism; mainLog = prism.getMainLog(); this.modulesFile = modulesFile; this.propertiesFile = propertiesFile; // Get combined constant values from model/properties constantValues = new Values(); constantValues.addValues(modulesFile.getConstantValues()); if (propertiesFile != null) constantValues.addValues(propertiesFile.getConstantValues()); // Build a combined label list and expand any constants // (note labels in model are ignored (removed) during PTA translation so need to store here) labelList = new LabelList(); for (int i = 0; i < modulesFile.getLabelList().size(); i++) { labelList.addLabel( modulesFile.getLabelList().getLabelNameIdent(i), modulesFile.getLabelList().getLabel(i).deepCopy()); } for (int i = 0; i < propertiesFile.getLabelList().size(); i++) { labelList.addLabel( propertiesFile.getLabelList().getLabelNameIdent(i), propertiesFile.getLabelList().getLabel(i).deepCopy()); } labelList = (LabelList) labelList.replaceConstants(constantValues); // Build mapping from all (original model) variables to non-clocks only int numVars = modulesFile.getNumVars(); nonClockVarMap = new int[numVars]; int count = 0; for (int i = 0; i < numVars; i++) { if (modulesFile.getVarType(i) instanceof TypeClock) { nonClockVarMap[i] = -1; } else { nonClockVarMap[i] = count++; } } }
/** * Determine which locations in the PTA satisfy a (Boolean) expression. Note: This is rather * inefficiently at the moment. TODO: potentially use explicit.StateMC on dummy model eventually */ private BitSet checkLocationExpression(Expression expr) throws PrismException { int i, n; BitSet res; // Labels - expand and recurse // (note: currently not used - these are expanded earlier) if (expr instanceof ExpressionLabel) { ExpressionLabel exprLabel = (ExpressionLabel) expr; if (exprLabel.getName().equals("deadlock")) throw new PrismException("The \"deadlock\" label is not yet supported for PTAs"); if (exprLabel.getName().equals("init")) throw new PrismException("The \"init\" label is not yet supported for PTAs"); i = labelList.getLabelIndex(exprLabel.getName()); if (i == -1) throw new PrismException("Unknown label \"" + exprLabel.getName() + "\" in property"); // Check recursively return checkLocationExpression(labelList.getLabel(i)); } // Other expressions... else { List<Object> states; // Object[] state; states = pta.getLocationNameList(); n = states.size(); res = new BitSet(n); for (i = 0; i < n; i++) { // state = (Object[])states.get(i); State state = (State) states.get(i); if (expr.evaluateBoolean(state, nonClockVarMap)) { res.set(i); } } } return res; }
/** * Assembles the source code. * * @throws IOException */ @Override public void assemble() throws IOException { // Do not assemble anything if there are no cases! if (this.casesList.isEmpty()) return; // Give each case a label. for (SwitchCaseStatement statement : this.casesList) statement.setLabel(LabelList.getCurrent().getNext()); if (this.defaultCase != null) this.defaultCase.setLabel(LabelList.getCurrent().getNext()); Label gotoEnd = LabelList.getCurrent().getNext(); Label gotoStart = LabelList.getCurrent().getNext(); // Go to the jump table which is assembled after the switch case labels and // statements. ScriptParser.writeLine("Goto " + gotoStart); // Using "break;" inside a switch jumps to the end. Label parentBreak = CodeInfo.getCurrent().setBreakLabel(gotoEnd); // Assemble all the statements inside the switch { }. This includes the // case labels. for (Statement statement : this.statementList) statement.assemble(); // Restore the parent break label. CodeInfo.getCurrent().setBreakLabel(parentBreak); // Label at the top of the jump table. gotoStart.write(); // Jump instructions can jump directly to the case labels. if (this.switchExpression instanceof JumpExpression) { ((JumpExpression) this.switchExpression).assemble(this.casesList); } // Other expressions we just assemble them if required and compare their // result. else { Expression varOrSwitchExpression = AssembleExpression.getRegisterOrExpression(this.switchExpression); for (SwitchCaseStatement caseStatement : this.casesList) { // Type is an integer; use IntCmp. if (caseStatement.getMatch().getType().equals(ExpressionType.Integer)) { ScriptParser.writeLine( String.format( "IntCmp %s %s %s", varOrSwitchExpression, caseStatement.getMatch(), caseStatement.getLabel())); } // Type is a string; use StrCmp or StrCmpS (if special `` quotes were // used). else { ScriptParser.writeLine( String.format( "StrCmp%s %s %s %s", caseStatement.getMatch().getType().equals(ExpressionType.StringSpecial) ? "S" : "", varOrSwitchExpression, caseStatement.getMatch(), caseStatement.getLabel())); } } varOrSwitchExpression.setInUse(false); } // Default case jump. if (this.defaultCase != null) ScriptParser.writeLine("Goto " + this.defaultCase.getLabel()); gotoEnd.write(); }