// Dynamic place contents -*- c++ -*-

#ifdef __GNUC__
# pragma implementation
#endif // __GNUC__
#include "PlaceContents.h"
#include <assert.h>
#include "Place.h"
#include "GlobalMarking.h"
#include "Valuation.h"
#include "Printer.h"

/** @file PlaceContents.C
 * Operation for reading the marking of a place
 */

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

PlaceContents::PlaceContents (const class Place& place) :
  myPlace (place)
{
  setType (place.getType ());
}

PlaceContents::~PlaceContents ()
{
}

class PlaceMarking*
PlaceContents::meval (const class Valuation& valuation) const
{
  if (const class GlobalMarking* m = valuation.getGlobalMarking ())
    return new class PlaceMarking ((*m)[myPlace]);
  else {
    valuation.flag (errVar, *this);
    return NULL;
  }
}

bool
PlaceContents::depends (const class VariableSet&,
			bool) const
{
  return false;
}

bool
PlaceContents::forExpressions (bool (*operation)
			       (const class Expression&,void*),
			       void* data) const
{
  return
    (*operation) (*this, data);
}

#ifdef EXPR_COMPILE
# include "CExpression.h"

void
PlaceContents::compileScalarMset (class CExpression& cexpr,
				  unsigned indent,
				  const char* result,
				  const class VariableSet*,
				  bool check) const
{
  class StringBuffer& out = cexpr.getOut ();
  if (check) {
    out.indent (indent);
    out.append ("if (");
    out.append (result);
    if (myPlace.getMaxNumTokens () == 1) {
      out.append (" && ");
      out.append (cexpr.getMultiset ());
      out.append (".p");
      out.append (myPlace.getIndex ());
    }
    else {
      out.append (" && singleton (");
      out.append (cexpr.getMultiset ());
      out.append (".p");
      out.append (myPlace.getIndex ());
      out.append (")");
    }
    out.append (")\n");
    cexpr.compileError (indent + 2, errConst);
  }
  if (myPlace.getMaxNumTokens () == 1) {
    out.indent (indent);
    out.append (result);
    out.append (" = ");
    out.append (cexpr.getMultiset ());
    out.append (".p");
    out.append (myPlace.getIndex ());
    out.append (";\n");
  }
  else {
    out.indent (indent);
    out.append (result);
    out.append (" = singleton (");
    out.append (cexpr.getMultiset ());
    out.append (".p");
    out.append (myPlace.getIndex ());
    out.append (");\n");
  }
}

void
PlaceContents::compileMset (class CExpression& cexpr,
			    unsigned indent,
			    const char* resulttype,
			    const char* result,
			    const class VariableSet*) const
{
  class StringBuffer& out = cexpr.getOut ();
  if (myPlace.getMaxNumTokens () == 1) {
    out.indent (indent);
    if (myPlace.getCapacityBits ()) {
      out.append ("if (");
      out.append (cexpr.getMultiset ());
      out.append (".p");
      out.append (myPlace.getIndex ());
      out.append (")\n");
      out.indent (indent + 2);
    }
    out.append (result);
    out.append ("=insert");
    getType ()->appendIndex (out);
    out.append (" (");
    if (resulttype)
      out.append (resulttype);
    out.append (result);
    out.append (", ");
    out.append (cexpr.getMultiset ());
    out.append (".p");
    out.append (myPlace.getIndex ());
    out.append (", 1);\n");
  }
  else {
    out.indent (indent);
    out.append (result);
    out.append ("=copy");
    getType ()->appendIndex (out);
    out.append (" (");
    if (resulttype)
      out.append (resulttype);
    out.append (result);
    out.append (", ");
    out.append (cexpr.getMultiset ());
    out.append (".p");
    out.append (myPlace.getIndex ());
    out.append (");\n");
  }
}

char*
PlaceContents::getName (const class CExpression& cexpr) const
{
  const char* mset = cexpr.getMultiset ();
  assert (!!mset);
  class StringBuffer buf;
  buf.append (mset);
  buf.append (".p");
  buf.append (myPlace.getIndex ());
  char* name = new char[buf.getLength () + 1];
  memcpy (name, buf.getString (), buf.getLength () + 1);
  return name;
}

#endif // EXPR_COMPILE

void
PlaceContents::display (const class Printer& printer) const
{
  printer.printRaw ("place");
  printer.delimiter (' ');
  printer.print (myPlace.getName ());
}
