2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.vm.choice;
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.JPFException;
22 import gov.nasa.jpf.vm.ChoiceGeneratorBase;
23 import gov.nasa.jpf.vm.StackFrame;
24 import gov.nasa.jpf.vm.ThreadInfo;
26 import java.util.Arrays;
27 import java.util.Comparator;
30 * common root for list based number choice generators
32 public abstract class NumberChoiceFromList<T extends Number> extends ChoiceGeneratorBase<T> {
34 // int values to choose from stored as Strings or Integers
36 protected int count = -1;
38 // TODO: Fix for Groovy's model-checking
39 // TODO: This is a setter to change the values of the ChoiceGenerator to implement POR
40 protected boolean isDpor = false;
43 * super constructor for subclasses that want to configure themselves
44 * @param id name used in choice config
46 protected NumberChoiceFromList(String id){
50 protected NumberChoiceFromList (String id, T[] vals){
57 protected abstract T[] createValueArray(int len);
58 protected abstract T getDefaultValue();
59 protected abstract T parseLiteral (String literal, int sign);
60 protected abstract T newValue (Number num, int sign);
63 * @param conf JPF configuration object
64 * @param id name used in choice config
66 public NumberChoiceFromList(Config conf, String id) {
69 String[] vals = conf.getCompactStringArray(id + ".values");
70 if (vals == null || vals.length == 0) {
71 throw new JPFException("no value specs for IntChoiceFromList " + id);
74 // get the choice values here because otherwise successive getNextChoice()
75 // calls within the same transition could see different values when looking
76 // up fields and locals
77 values = createValueArray(vals.length);
78 StackFrame resolveFrame = ThreadInfo.getCurrentThread().getLastNonSyntheticStackFrame();
79 for (int i=0; i<vals.length; i++){
80 values[i] = parse(vals[i], resolveFrame);
85 public T getChoice (int idx){
86 if (idx >=0 && idx < values.length){
89 throw new IllegalArgumentException("choice index out of range: " + idx);
94 public void reset () {
101 * @see gov.nasa.jpf.vm.IntChoiceGenerator#getNextChoice()
104 public T getNextChoice() {
106 if ((count >= 0) && (count < values.length)) {
107 return values[count];
110 return getDefaultValue();
114 * @see gov.nasa.jpf.vm.ChoiceGenerator#hasMoreChoices()
117 public boolean hasMoreChoices() {
118 // TODO: Fix for Groovy's model-checking
119 // TODO: This is a setter to change the values of the ChoiceGenerator to implement POR
126 /* TODO: ORIGINAL CODE*/
127 if (!isDone && (count < values.length - 1))
135 * @see gov.nasa.jpf.vm.ChoiceGenerator#advance()
138 public void advance() {
139 // TODO: Fix for Groovy's model-checking
140 // TODO: This is a setter to change the values of the ChoiceGenerator to implement POR
142 // TODO: We make this circular
144 if (count < values.length - 1) count++;
147 /* TODO: ORIGINAL CODE*/
148 if (count < values.length - 1) count++;
153 * get String label of current value, as specified in config file
155 public String getValueLabel(){
156 return values[count].toString();
160 public int getTotalNumberOfChoices () {
161 return values.length;
165 public int getProcessedNumberOfChoices () {
170 public boolean supportsReordering(){
175 protected T parse (String varSpec, StackFrame resolveFrame){
178 char c = varSpec.charAt(0);
180 varSpec = varSpec.substring(1);
181 } else if (c == '-'){
183 varSpec = varSpec.substring(1);
186 if (varSpec.isEmpty()){
187 throw new JPFException("illegal value spec for IntChoiceFromList " + id);
190 c = varSpec.charAt(0);
191 if (Character.isDigit(c)){ // its an integer literal
192 return parseLiteral(varSpec, sign);
194 } else { // a variable or field name
195 Object o = resolveFrame.getLocalOrFieldValue(varSpec);
197 throw new JPFException("no local or field '" + varSpec + "' value found for NumberChoiceFromList " + id);
199 if (o instanceof Number){
200 return newValue( (Number)o, sign);
202 throw new JPFException("non-numeric local or field '" + varSpec + "' value for NumberChoiceFromList " + id);
209 public NumberChoiceFromList<T> reorder (Comparator<T> comparator){
211 T[] newValues = values.clone();
212 Arrays.sort( newValues, comparator);
214 // we can't instantiate directly
216 NumberChoiceFromList<T> clone = (NumberChoiceFromList<T>)clone();
217 clone.values = newValues;
221 } catch (CloneNotSupportedException cnsx){
223 throw new JPFException("can't clone NumberChoiceFromList " + this);
228 public String toString() {
229 StringBuilder sb = new StringBuilder(getClass().getName());
234 sb.append(",isCascaded:");
235 sb.append(isCascaded);
238 for (int i=0; i<values.length; i++) {
245 sb.append(values[i]);
248 return sb.toString();
253 public NumberChoiceFromList<T> randomize () {
254 for (int i = values.length - 1; i > 0; i--) {
255 int j = random.nextInt(i + 1);
257 values[i] = values[j];
263 // TODO: Fix for Groovy's model-checking
264 // TODO: This is a setter to change the values of the ChoiceGenerator to implement POR
265 public void setNewValues(T[] vals) {
269 public int getNextChoiceIndex() {
273 public void setChoice(int idx, T value) {
274 if ((idx >= 0) && (idx < values.length)) {
277 throw new JPFException("illegal value " + idx + " for array index");
281 public void setDpor() {