// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: variable.cpp 816 2011-09-10 13:19:07Z Sebastian Kupferschmid $
//
////////////////////////////////////////////////////////////////////

#include "variable.h"

#include <cassert>
#include <ostream>

using namespace std;

////////////////////////////////////////////////////////////////////

Channel::Channel(const std::string& name, int32_t id) : 
    Variable(name, Expression::CHANNEL),
    urgent(false), 
    broadcast(false),
    id(id)
{}

ostream& Channel::display(ostream& o) const {
    if (urgent) { 
	o << "urgent ";
    } 
    if (broadcast) {
	o << "broadcast ";
    }
    return o << "chan " << name;
}

////////////////////////////////////////////////////////////////////

Action::Action(Channel* chan, bool isBang) : 
    Variable(chan->name, Expression::ACTION),
    chan(chan),
    isBang(isBang),
    id(chan->id)
{
    assert(chan);
}

ostream& Action::display(ostream& o) const {
    assert(chan);
    return o << chan->name << (isBang ? "!" : "?");
}

////////////////////////////////////////////////////////////////////

Clock::Clock(const string& name, int32_t id) :     
    Variable(name, Expression::CLOCK),
    id(id)
{}

ostream& Clock::display(ostream& o) const {
    return o << "clock " << name;
}

////////////////////////////////////////////////////////////////////

Constant::Constant(const string& name) : 
    Variable(name, Expression::CONSTANT),
    value(0) 
{}

Constant::Constant(const string& name, int32_t value) :
    Variable(name, Expression::CONSTANT),
    value(value) 
{}

ostream& Constant::display(std::ostream& o) const {
    return o << "(const " << name << " := " << value << ")";
}

////////////////////////////////////////////////////////////////////

ConstantFactory::ConstantFactory() :
    constants() 
{}

ConstantFactory::~ConstantFactory() {
    for (map_t::iterator it = constants.begin(); it != constants.end(); ++it) {
        delete it->second;
    }
}

Constant* ConstantFactory::newConstant(int32_t value) {
    static ConstantFactory factory;
    pair<map_t::iterator, bool> pos = factory.constants.insert(
	make_pair(value, static_cast<Constant*>(NULL)));
    if (pos.second) {
	pos.first->second = new Constant("tmp", value);
    }
    return pos.first->second;
}

////////////////////////////////////////////////////////////////////

Integer::Integer(const std::string& name, int32_t id) :
    Variable(name, Expression::INTEGER), 
    initial(0),
    id(id)
{}

ostream& Integer::display(ostream& o) const {
    o << "int";
    if (lower != MIN_BOUND || upper != MAX_BOUND) {
	o << "[" << lower << "," << upper << "]";
    }
    return o << " " << name <<  " := " << initial;
}
