/**
     * process the sample by checking it against each existing invariant and issuing an error if any
     * invariant is falsified or weakened.
     */
    public void process_sample(PptMap all_ppts, PptTopLevel ppt, ValueTuple vt, Integer nonce) {

      this.all_ppts = all_ppts;

      debug.fine("processing sample from: " + ppt.name);

      // Add orig and derived variables
      FileIO.add_orig_variables(ppt, vt.vals, vt.mods, nonce);
      FileIO.add_derived_variables(ppt, vt.vals, vt.mods);

      // Intern the sample
      vt = new ValueTuple(vt.vals, vt.mods);

      // If this is an enter point, just remember it for later
      if (ppt.ppt_name.isEnterPoint()) {
        Assert.assertTrue(nonce != null);
        if (dir_file != null) {
          // Yoav: I had to do a hack to handle the case that several dtrace files are concatenated
          // together,
          // and Sung's dtrace files have unterminated calls, and when concatenating two files you
          // can have the same nonce.
          // So I have to remove the nonce found from the call_map
          call_map.remove(nonce);
        } else Assert.assertTrue(call_map.get(nonce) == null);
        call_map.put(nonce, new EnterCall(ppt, vt));
        debug.fine("Skipping enter sample");
        return;
      }

      // If this is an exit point, process the saved enter point
      if (ppt.ppt_name.isExitPoint()) {
        Assert.assertTrue(nonce != null);
        EnterCall ec = call_map.get(nonce);
        if (ec != null) {
          call_map.remove(nonce);
          debug.fine("Processing enter sample from " + ec.ppt.name);
          add(ec.ppt, ec.vt);
        } else { // didn't find the enter
          if (!quiet)
            System.out.printf("couldn't find enter for nonce %d at ppt %s\n", nonce, ppt.name());
          return;
        }
      }

      add(ppt, vt);
    }
    /**
     * Creates a valuetuple for the receiver using the vt of the original. The method copies over
     * the values of variables shared by both program points and sets the rest of the variables in
     * the receiver's valuetuple as missing. Also, adds the orig and derived variables to the
     * receiver and returns the newly created valuetuple.
     */
    private static ValueTuple copySample(
        PptTopLevel receiver, PptTopLevel original, ValueTuple vt, int nonce) {

      // Make the vt for the receiver ppt
      //      Object values[] = new Object[receiver.num_tracevars];
      //      int mods[] = new int[receiver.num_tracevars];
      Object values[] = new Object[receiver.var_infos.length - receiver.num_static_constant_vars];
      int mods[] = new int[receiver.var_infos.length - receiver.num_static_constant_vars];

      // Build the vt for the receiver ppt by looking through the current
      // vt and filling in the gaps.
      int k = 0;
      for (Iterator<VarInfo> i = receiver.var_info_iterator(); i.hasNext(); ) {

        VarInfo var = i.next();
        if (var.is_static_constant) continue;
        boolean found = false;
        for (Iterator<VarInfo> j = original.var_info_iterator(); j.hasNext(); ) {
          VarInfo var2 = j.next();

          if (var.name().equals(var2.name())) {
            values[k] = vt.getValueOrNull(var2);
            mods[k] = vt.getModified(var2);
            found = true;
            break;
          }
        }

        if (!found) {
          values[k] = null;
          mods[k] = 2;
        }
        k++;
      }

      ValueTuple receiver_vt = new ValueTuple(values, mods);

      FileIO.add_orig_variables(receiver, receiver_vt.vals, receiver_vt.mods, nonce);
      FileIO.add_derived_variables(receiver, receiver_vt.vals, receiver_vt.mods);

      return receiver_vt;
    }
    /**
     * Process the sample by checking it against each existing invariant at the program point and
     * removing the invariant from the list of possibles if any invariant is falsified.
     */
    public void process_sample(
        PptMap all_ppts, PptTopLevel ppt, ValueTuple vt, /*@Nullable*/ Integer nonce) {
      this.all_ppts = all_ppts;

      // Add samples to orig and derived variables
      FileIO.add_orig_variables(ppt, vt.vals, vt.mods, nonce);
      FileIO.add_derived_variables(ppt, vt.vals, vt.mods);

      // Intern the sample
      vt = new ValueTuple(vt.vals, vt.mods);

      // DaikonSimple must make the object program point manually because
      // the new Chicory produced dtrace files do not contain object ppts
      // in the dtrace part of the file (the program point is declared).

      // Make the object ppt
      PptName ppt_name = ppt.ppt_name;

      PptTopLevel object_ppt = null;
      PptTopLevel class_ppt = null;
      ValueTuple object_vt = null;
      ValueTuple class_vt = null;

      if ((ppt_name.isEnterPoint() && !ppt_name.isConstructor()) || ppt_name.isExitPoint()) {
        object_ppt = all_ppts.get(ppt_name.makeObject());
        class_ppt = all_ppts.get(ppt_name.makeClassStatic());
      }

      // C programs do not have object ppts
      // check whether the ppt is a static or instance method
      // that decides whether the sample is copied over to the object and/or
      // class ppt
      if (object_ppt != null) {

        // the check assumes that static fields are not stored first in the
        // object ppt
        if (ppt.find_var_by_name(object_ppt.var_infos[0].name()) != null) {
          // object and class ppt should be created
          object_vt = copySample(object_ppt, ppt, vt, nonce);

          if (class_ppt != null) {
            class_vt = copySample(class_ppt, ppt, vt, nonce);
          }

        } else {
          // only class ppt should be created
          if (class_ppt != null) {
            class_vt = copySample(class_ppt, ppt, vt, nonce);
          }

          object_vt = null;
          object_ppt = null;
        }
      }

      // If this is an enter point, just remember it for later
      if (ppt_name.isEnterPoint()) {
        assert nonce != null;
        assert call_map.get(nonce) == null;
        List<Call> value = new ArrayList<Call>();
        value.add(new Call(ppt, vt));

        if (object_ppt != null) {
          value.add(new Call(object_ppt, object_vt));
        }

        if (class_ppt != null) {
          value.add(new Call(class_ppt, class_vt));
        }

        call_map.put(nonce, value);
        last_nonce = nonce;
        wait = true;
        return;
      }

      // If this is an exit point, process the saved enter (and sometimes
      // object) point
      if (ppt_name.isExitPoint()) {
        assert nonce != null;
        List<Call> value = call_map.remove(nonce);

        add(ppt, vt, nonce);

        for (Call ec : value) {
          add(ec.ppt, ec.vt, nonce);
        }
        wait = false;
      }

      if (object_ppt != null) add(object_ppt, object_vt, nonce); // apply object vt

      if (class_ppt != null) add(class_ppt, class_vt, nonce);
    }