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

#ifndef SYSTEM_VARIABLE_H
#define SYSTEM_VARIABLE_H

#include "expression.h"

#include <inttypes.h>
#include <map>
#include <string>

/** Variable is the base class for all variabes, e.g. Integers, Clocks.
 **/
class Variable : public Expression {
public:
    std::string name;
    
    Variable(const std::string& name, Expression::type_t type) : 
	Expression(type), 
	name(name) 
	{}
};

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

class Channel : public Variable {
public:
    bool urgent;
    bool broadcast;
    int32_t id;
    
    explicit Channel(const std::string& name, int32_t id);

    virtual std::ostream& display(std::ostream& o) const;    
};

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

/* An Action is mainly a pointer to a Channel. It has the same id as
 * the Channel.
 */
class Action : public Variable {
public:
    Channel* chan;
    bool isBang;
    int32_t id;
    
    Action(Channel* chan, bool isBang);

    bool operator==(const Action& other) const {
	return chan == other.chan && isBang == other.isBang;
    }
    bool operator!=(const Action& other) const {
	return !(*this == other);
    }
    virtual std::ostream& display(std::ostream& o) const;
};

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

class Clock : public Variable {
public:
    int32_t id;
    explicit Clock(const std::string& name, int32_t id);

    virtual std::ostream& display(std::ostream& o) const;
};

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

class Constant : public Variable {
public:
    int32_t value;
    
    explicit Constant(const std::string& name);
    Constant(const std::string& name, int32_t value);

    virtual std::ostream& display(std::ostream& o) const;
};

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

/** As there are normaly many Constants representing the same value,
 * prefere to use this factory for creating Constants.
 **/
class ConstantFactory {
private:
    typedef std::map<int32_t, Constant*> map_t;
    map_t constants;
    
    ConstantFactory();
    ~ConstantFactory();    
public:
    static Constant* newConstant(int32_t value);
};

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

class Integer : public Variable {
public:
    static const int32_t MAX_BOUND = 1 << 15;
    static const int32_t MIN_BOUND = -MAX_BOUND;
   
    int32_t lower;
    int32_t upper;
    int32_t initial;
    int32_t id;
    
    explicit Integer(const std::string& name, int32_t id);    
    virtual std::ostream& display(std::ostream& o) const;
};

#endif /* SYSTEM_VARIABLE_H */
