diff src/main/gov/nasa/jpf/util/script/EventGeneratorFactory.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/gov/nasa/jpf/util/script/EventGeneratorFactory.java	Fri Jan 23 10:14:01 2015 -0800
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2014, United States Government, as represented by the
+ * Administrator of the National Aeronautics and Space Administration.
+ * All rights reserved.
+ *
+ * The Java Pathfinder core (jpf-core) platform is licensed under the
+ * Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ * 
+ *        http://www.apache.org/licenses/LICENSE-2.0. 
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package gov.nasa.jpf.util.script;
+
+import gov.nasa.jpf.Config;
+import gov.nasa.jpf.ListenerAdapter;
+import gov.nasa.jpf.search.Search;
+import gov.nasa.jpf.util.DynamicObjectArray;
+import gov.nasa.jpf.vm.ChoiceGenerator;
+import gov.nasa.jpf.vm.SystemState;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+
+/**
+ * abstract root for backtrackable event generator factories
+ *
+ * <2do> - we don't support backtracking for sections yet! needs to be implemented for
+ * state charts
+ */
+public abstract class EventGeneratorFactory extends ListenerAdapter
+                                         implements ElementProcessor, Iterable<EventGenerator> {
+
+  static final String DEFAULT = "default";
+
+  // helper class to store our internal state. For a simple script based system,
+  // storing the 'cur' index (into the queue) would do, but the queue might have been
+  // generated dynamically, so we need some container to store both
+  static class Memento {
+    ArrayList<EventGenerator> queue;
+    int cur; // cursor into queue
+
+    Memento (EventGeneratorFactory fact) {
+      queue = fact.queue;
+      cur = fact.cur;
+    }
+
+    void restore (EventGeneratorFactory fact) {
+      fact.queue = queue;
+      fact.cur = cur;
+    }
+  }
+
+
+  // <2do> this is lame - if we really want 'instructions' in the queue, rather
+  // than data (== CGs), then we should have a queue of general EventOp entries
+  // this is only used for unbounded REPEATs so far
+  // <2do> the nextCG is currently unconditionally reset in getNextChoiceGenerator()
+  // so we have to make sure we don't jump back if the jump target state was already
+  // visited, which we have to store in the Jump
+  static class Loop extends EventGenerator {
+
+    int startPos, endPos;
+
+    Loop (String id, int startPos,  int endPos){
+      super(id);
+      
+      this.startPos = startPos;
+      this.endPos = endPos;
+    }
+
+    int getStartPos() {
+      return startPos;
+    }
+
+    //--- those are all dummies - this isn't really a choice
+    @Override
+	public void advance() {}
+
+    @Override
+	public Class getChoiceType() {
+      return null;
+    }
+
+    @Override
+	public Object getNextChoice() {
+      return null;
+    }
+
+    @Override
+	public int getProcessedNumberOfChoices() {
+      return 0;
+    }
+
+    @Override
+	public int getTotalNumberOfChoices() {
+      return 0;
+    }
+
+    @Override
+	public boolean hasMoreChoices() {
+      return false;
+    }
+
+    @Override
+	public ChoiceGenerator randomize() {
+      return null;
+    }
+
+    @Override
+	public void reset() {}
+
+  }
+
+  /** the last returned position in the generator stream */
+  protected int cur;
+
+  /** this is where we store the cur positions for backtracking and restoring states */
+  DynamicObjectArray<Memento> states;
+
+  protected String scriptFileName;
+  protected Script script;
+  protected Config conf;
+
+  protected LinkedHashMap<String,ArrayList<EventGenerator>> sections;
+  protected ArrayList<EventGenerator> queue;
+
+  EventFactory efact;
+
+  protected EventGeneratorFactory () {
+    efact = null;
+  }
+
+  protected EventGeneratorFactory (EventFactory efact) {
+    this.efact = efact;
+  }
+
+  protected void init (String fname) throws ESParser.Exception {
+    cur = 0;
+    states = new DynamicObjectArray<Memento>();
+
+    sections = new LinkedHashMap<String,ArrayList<EventGenerator>>();
+    queue = new ArrayList<EventGenerator>();
+    sections.put(DEFAULT, queue);
+
+    ESParser parser= new ESParser(fname, efact);
+    script = parser.parse();
+    scriptFileName = fname;
+
+    script.process(this);
+  }
+
+  @Override
+  public Iterator<EventGenerator> iterator() {
+    return queue.iterator();
+  }
+
+  protected void addLoop (int startPos) {
+    queue.add( new Loop( "loop", startPos, queue.size()-1));
+  }
+
+  public abstract Class<?> getEventType();
+
+  /**
+   * reset the enumeration state of this factory
+   */
+  public void reset () {
+    cur = 0;
+  }
+
+  public String getScriptFileName() {
+    return scriptFileName;
+  }
+
+  public Script getScript() {
+    return script;
+  }
+
+  public boolean hasSection (String id) {
+    return sections.containsKey(id);
+  }
+
+  public ArrayList<EventGenerator> getSection (String id) {
+    return sections.get(id);
+  }
+
+  public ArrayList<EventGenerator> getDefaultSection () {
+    return sections.get(DEFAULT);
+  }
+
+  protected void setQueue (ArrayList<EventGenerator> q) {
+    if (queue != q) {
+      queue = q;
+      cur = 0;
+    }
+  }
+
+  protected EventGenerator getNextEventGenerator() {
+    EventGenerator cg;
+    int n = queue.size();
+
+    if (n == 0) {
+      return null; // nothing to do
+    }
+
+    if (cur < n) {
+      cg = getQueueItem(cur); // might clone the queue item
+
+      // <2do> - this is a BAD hot fix, but it's going away soon!
+      if (cg instanceof Loop) {
+        int tgtPos = ((Loop)cg).getStartPos();
+        cg = queue.get(tgtPos);
+
+        if (!cg.hasMoreChoices()) {
+          for (int i=tgtPos; i<cur; i++) {
+            queue.get(i).reset();
+          }
+        }
+
+        cur = tgtPos;
+      }
+
+      cg.setId(Integer.toString(cur));
+
+      // might be reused if we re-enter a section sequence or REPEAT body, so we have to reset
+      // <2do> - commenting this out leads to premature state matching on model loops
+      // (will be fixed by the revamped environment modeling)
+      //cg.reset();
+
+      cur++;
+      return cg;
+
+    } else {
+      return null; // nothing left
+    }
+  }
+
+  // we encapsulate this because it might require cloning
+  protected EventGenerator getQueueItem (int i) {
+    return queue.get(i);
+  }
+
+
+  public int getTotalNumberOfEvents() {
+    int total=0;
+    int last = 1;
+
+    for (EventGenerator cg : queue) {
+       int level = cg.getTotalNumberOfChoices() * last;
+       total += level;
+       last = level;
+    }
+
+    return total;
+  }
+
+  public void printOn (PrintWriter pw) {
+    for (EventGenerator eg : queue) {
+      pw.println(eg);
+    }
+  }
+
+  /************************************** SearchListener interface **************/
+  /* we need this after a backtrack and restore to determine the next CG to return
+   */
+
+  @Override
+  public void searchStarted (Search search) {
+    cur = 0;
+  }
+
+  @Override
+  public void stateAdvanced (Search search) {
+    int idx = search.getStateId();
+
+    if (idx >= 0) { // <??> why would it be notified for the init state?
+      Memento m = new Memento(this);
+      states.set(idx, m);
+    }
+  }
+
+  @Override
+  public void stateBacktracked (Search search) {
+    Memento m = states.get(search.getStateId());
+    m.restore(this);
+    // nextCg will be re-computed (->getNext), so there is no need to reset
+  }
+
+  @Override
+  public void stateRestored (Search search) {
+    Memento m = states.get(search.getStateId());
+    m.restore(this);
+
+    // nextCg is restored (not re-computed), so we need to reset
+    SystemState ss = search.getVM().getSystemState();
+    ChoiceGenerator cgNext = ss.getNextChoiceGenerator();
+    cgNext.reset();
+  }
+
+}