// Place class -*- c++ -*-

#ifdef __GNUC__
# pragma implementation
#endif // __GNUC__
#include "Place.h"
#include "Constraint.h"
#include "Arc.h"
#include "Marking.h"
#include "CardType.h"
#include "LeafValue.h"
#include "PlaceMarking.h"
#include "Printer.h"
#include "util.h"

/** @file Place.C
 * Place in an algebraic system net
 */

/* Copyright © 1998-2003 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. */

Place::Place (const class Net& net,
	      unsigned i,
	      char* name,
	      class Constraint* capacity,
	      const class Type& type) :
  myNet (net), myIndex (i), myName (name), myCapacity (capacity),
  myCapacityBits (CARD_T_BIT), myType (&type),
  myInitMarking (0), myIsImplicit (false), myIsVisible (false),
  myIsNonempty (false), myIsConstant (false),
  myIsSuppressed (false), myMaxNumTokens (CARD_T_MAX)
{
  if (myCapacity) {
    myCapacityBits = log2 (myCapacity->getNumValues ());
    card_t n;
    if (!CardType::convert (n, 0, *myCapacity))
      myIsNonempty = true;

    const class Value& v = myCapacity->getLastValue ();
    assert (v.getKind () == Value::vLeaf);
    myMaxNumTokens = card_t (static_cast<const class LeafValue&>(v));
  }
}

Place::~Place ()
{
  delete[] myName;
  delete myCapacity;
  myInitMarking->destroy ();
}

void
Place::setInitMarking (class Marking& initMarking)
{
  assert (!myInitMarking && !myIsImplicit);
  myInitMarking = &initMarking;
  if ((myIsImplicit = myIsConstant))
    return;
  class Valuation v;
  if (class PlaceMarking* p = myInitMarking->meval (v))
    delete p;
  else
    myIsImplicit = true;
}

void
Place::display (const class Printer& printer) const
{
  printer.printRaw ("place");
  printer.delimiter (' ');
  printer.print (myName);

  if (myCapacity) {
    printer.delimiter (' ');
    myCapacity->display (printer);
  }

  printer.delimiter (' ');
  if (const char* name = myType->getName ())
    printer.print (name);
  else
    myType->display (printer);

  if (myIsConstant) {
    printer.delimiter (' ');
    printer.printRaw ("const");
  }

  if (myInitMarking) {
    printer.delimiter (':');
    myInitMarking->display (printer);
  }

  printer.delimiter (';');
  printer.finish ();
}
