Logo Search packages:      
Sourcecode: maria version File versions

void Transition::analyze ( class GlobalMarking m,
class StateReporter reporter 
) const

Determine all enabled instances of the transition for a marking

Parameters:
m the marking to be analyzed
reporter the interface for reporting successors or errors

processed tokens

tokens removed from the input places

Placeholder for the successor state

Definition at line 1500 of file Transition.C.

References TokenList::begin(), slist< T >::begin(), checkGates(), TokenList::empty(), PlaceMarking::empty(), slist< T >::empty(), TokenList::end(), fireOutputs(), firstOutput(), Valuation::flagUndefined(), Token::free(), Value::getKind(), getKind(), Expression::getLvalues(), Marking::getMultiplicity(), Marking::getToken(), interrupted, TokenList::isCompatible(), StateReporter::isFatal(), Valuation::isOK(), Token::isReserved(), unif::isSet, unif::m, myGates, myKind, myNumParents, myOutputMarking, myUnif, unif::next, nextOutput(), unif::place, TokenList::pop(), TokenList::push(), StateReporter::reject(), StateReporter::reportSync(), Valuation::setGlobalMarking(), unif::varMult, unif::vars, and willDo().

Referenced by StateReporter::analyzeFlattened(), StateReporter::analyzeModular(), GraphReporter::analyzeModular(), StateSetReporter::displayPath(), GraphReporter::getSuccessors(), and sync().

{
  if (!myGates.empty () &&
      (*myGates.begin ())->getKind () == Expression::eConstant) {
    // there is a constant gate (which should be always disabled):
    // ignore the transition
#ifndef NDEBUG
    const class Expression* g = *myGates.begin ();
    const class Value& v = static_cast<const class Constant*>(g)->getValue ();
    assert (v.getKind () == Value::vLeaf);
    assert (!bool (static_cast<const class LeafValue&>(v)));
#endif // NDEBUG
    return;
  }

  class Valuation valuation;
  const struct unif* u = myUnif;
  /** processed tokens */
  class TokenList tokens;

  for (class Token* token = 0;;) {
    assert (valuation.isOK ());
    // get next input arc inscription (abstract token) to be unified
    if (u) { // have all arc inscriptions been processed?
      // evaluate the multiplicity of the token
      if (card_t mult = u->m->getMultiplicity (valuation)) {
      assert (valuation.isOK ());
      class PlaceMarking& pm = m[u->place];
      token = !u->isSet && pm.empty ()
        ? 0
        : new class Token (mult, pm, *u);
      }
      else if (valuation.isOK ()) { // zero multiplicity => skip the token
      u = u->next;
      continue;
      }
      else
      goto unifError;

      if (token) {
      if (!u->vars) {
        // Any variables in the token have been unified before.
        // Evaluate the token and see if it is present in the input place.
        if (token->isBindable (valuation)) {
          // reserve the token and advance to the next one
        bindToken:
          assert (valuation.isOK ());
          token->reserve ();
          tokens.push (*token);
          token = 0;
          u = u->next;
          continue;
        }
        delete token;
        if (!valuation.isOK ()) {
          // report unification error and backtrack
        unifError:
          willDo (false, *this, valuation, m, reporter, "unification:");
        }
      }
      else { // some variables must be unified from the token
        if (u->varMult)
          token->addUnified (valuation);
        for (;;) {
#ifndef NDEBUG
          token->assertUndefined (valuation);
#endif // NDEBUG

          if (!token->getConcrete ());
          else if (willDo (token->isCompatible (valuation),
                       *this, valuation, m, reporter)) {
            u->m->getToken ()->getLvalues (token->getValue (),
                                   valuation, *u->vars);
#ifndef NDEBUG
            token->assertDefined (valuation);
#endif // NDEBUG
            if (willDo (checkGates (valuation) &&
                    token->isCompatible (valuation) &&
                    tokens.isCompatible (valuation),
                    *this, valuation, m, reporter))
            goto bindToken;
          incompatible:
            token->undefine (valuation);
            goto incompatible2;
          }
          else {
          incompatible2:
            if (interrupted || reporter.isFatal ())
            return;
            if (token->next ())
            continue;
          }

          delete token;
          break;
        }
      }
      }
    }
    // everything unified => try to fire the transition
    else if (myKind) {
      // an assertion transition is enabled
      valuation.flagUndefined (myKind == tFatal);
      reporter.reject (*this, valuation, m, "undefined gate", 0);
      // clean up the unification stack and return
      while (!tokens.empty ())
      if ((token = &tokens.pop ())->isReserved ())
        token->free ();
      return;
    }
    else if (!willDo (true, *this, valuation, m, reporter,
                  checkGates (valuation, errNone)
                  ? 0 : "undefined gate:"));
    else if (myNumParents)
      reporter.reportSync (*this);
    else if (firstOutput (*this, valuation, m, reporter)) {
      /** tokens removed from the input places */
      class GlobalMarking* inputs = 0;
      if (myOutputMarking) {
      inputs = new class GlobalMarking (reporter.net);
      for (TokenList::const_iterator t = tokens.begin ();
           t != tokens.end (); t++) {
        const struct unif& unif = (*t)->getUnifier ();
        class PlaceMarking& pm = (*inputs)[unif.place];
        if (!(*t)->copyRemoved (pm))
          assert (false);
      }
      }
      valuation.setGlobalMarking (inputs);

      // Fire the transition for all allowed bindings of output variables
      do {
      /** Placeholder for the successor state */
      class GlobalMarking successor (m);
      // Evaluate the output arcs and add the resulting state
      fireOutputs (*this, valuation, successor, reporter);
      }
      while (!interrupted && !reporter.isFatal () &&
           nextOutput (*this, valuation, m, reporter));

      valuation.setGlobalMarking (0);
      delete inputs;
    }

    // Backtrack in the search
    while (!tokens.empty ()) {
      token = &tokens.pop ();

      // Restore the reserved token to the input place
      if (token->isReserved ())
      token->free ();

      // If the token is "constant", backtrack further
      if (!(u = &token->getUnifier ())->vars) {
      delete token;
      continue;
      }

      goto incompatible;
    }
    break;
  }
}


Generated by  Doxygen 1.6.0   Back to index