// Quantifier expression -*- c++ -*-

#ifndef QUANTIFIER_H_
# define QUANTIFIER_H_
# ifdef __GNUC__
#  pragma interface
# endif // __GNUC__

# include "Expression.h"
# include <assert.h>
# include "s_list.h"

/** @file Quantifier.h
 * Quantifier variables
 */

/* Copyright © 1998-2002 Marko Mäkelä (msmakela@tcs.hut.fi).

   This file is part of MARIA, a reachability analyzer and model checker
   for high-level Petri nets.

   MARIA is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   MARIA is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */

/** Quantifier variable */
class Quantifier
{
public:

  /** Result of a check */
  enum Result { undefined, pass, fail };

  /** Constructor
   * @param name	variable name
   * @param type	variable type
   * @param condition	optional condition for the quantifier
   */
  Quantifier (char* name, const class Type& type,
	      class Expression* condition);

  /** Constructor
   * @param variable	variable
   * @param condition	optional condition for the quantifier
   */
  Quantifier (class VariableDefinition& variable,
	      class Expression* condition);

private:
  /** Copy constructor */
  Quantifier (const class Quantifier& old);
  /** Assignment operator */
  class Quantifier& operator= (const class Quantifier& old);
public:
  /** Destructor */
  ~Quantifier ();

  /** Determine the variable */
  const class VariableDefinition& getVariable () const { return *myVariable; }
  /** Determine the condition expression */
  const class Expression* getCondition () const { return myCondition; }
  /** Set the condition expression */
  void setCondition (class Expression& condition) {
    assert (!myCondition); myCondition = &condition;
  }

  /** Determine whether the given valuation is accepted by submarking criteria
   * @param valuation	Valuation to be checked
   * @return		(@see Result)
   */
  enum Result isAcceptable (const class Valuation& valuation) const;

  /** Equality comparison operator */
  bool operator== (const class Quantifier& other) const {
    return myVariable == other.myVariable &&
      *myCondition == *other.myCondition;
  }

  /** Ordering comparison operator */
  bool operator< (const class Quantifier& other) const {
    if (myVariable < other.myVariable) return true;
    if (other.myVariable < myVariable) return false;
    return *myCondition < *other.myCondition;
  }

private:
  /** Variable */
  class VariableDefinition* myVariable;
  /** Quantifier condition */
  class Expression* myCondition;
};

/** Quantifier variable list */
class QuantifierList
{
public:
  /** List of quantifier variables */
  typedef slist<class Quantifier*> List;
  /** Iterator to the quantifier list */
  typedef List::iterator iterator;
  /** Constant iterator to the quantifier list */
  typedef List::const_iterator const_iterator;

  /** Constructor */
  QuantifierList ();
private:
  /** Copy constructor */
  QuantifierList (const QuantifierList& old);
  /** Assignment operator */
  class QuantifierList& operator= (const class QuantifierList& old);
public:
  /** Destructor */
  ~QuantifierList ();

  /** Prepend a quantifier to the list
   * @param quantifier	quantifier to be prepended
   */
  void prepend (class Quantifier& quantifier) {
    myList.push_front (&quantifier);
  }
  /** Append a quantifier to the list
   * @param quantifier	quantifier to be appended
   */
  void append (class Quantifier& quantifier) {
    myList.insert (end (), &quantifier);
  }

  /** @name Accessors to the quantifier list */
  /*@{*/
  bool empty () const { return myList.empty (); }
  size_t size () const { return myList.size (); }
  const_iterator begin () const { return myList.begin (); }
  const_iterator end () const { return myList.end (); }
  iterator begin () { return myList.begin (); }
  iterator end () { return myList.end (); }
  /*@}*/

  /** Equality comparison operator */
  bool operator== (const class QuantifierList& other) const {
    if (size () != other.size ())
      return false;
    for (const_iterator i = begin (), j = other.begin ();
	 i != end (); i++, j++)
      if (!(**i == **j))
	return false;
    return true;
  }

  /** Ordering comparison operator */
  bool operator< (const class QuantifierList& other) const {
    if (size () < other.size ())
      return true;
    if (other.size () < size ())
      return false;
    for (const_iterator i = begin (), j = other.begin ();
	 i != end (); i++, j++)
      if (**i < **j)
	return true;
      else if (**j < **i)
	return false;
    return false;
  }

  /** Augment a valuation with the first values of the quantifiers
   * @param valuation	valuation to be augmented
   * @return		pass, fail (invalid valuation) or undefined (error)
   */
  enum Quantifier::Result augment (class Valuation& valuation) const;

  /** Step to the next values of the quantifiers
   * @return		pass, fail (wrapped) or undefined (error)
   */
  enum Quantifier::Result advance (class Valuation& valuation) const;

  /** Clear a valuation from assignments to the quantifiers
   * @param valuation	valuation to be cleared
   */
  void clear (class Valuation& valuation) const;

private:
  /** The list of quantifiers */
  List myList;
};

#endif // QUANTIFIER_H_
