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

#include "assignment.h"
#include "effect.h"
#include "state.h"

#include "common/helper.h"

#include <boost/foreach.hpp>
#include <cassert>
#include <ostream>
#define foreach BOOST_FOREACH

using namespace std;

Effect::Effect() :
    Expression(Expression::EFFECT),
    intassigns(),
    resets()
{}

bool Effect::operator==(const Effect& eff) const {
    if (intassigns.size() == eff.intassigns.size()) {
	set<const IntAssignment*> self, other;
	for (uint32_t i = 0; i < intassigns.size(); i++) {
	    self.insert(intassigns[i]);
	    other.insert(eff.intassigns[i]);
	}
	if (self != other) {
	    return false;
	}
    } else {
	return false;
    }
    if (resets.size() == eff.resets.size()) {
	set<const ClockReset*> self, other;
	for (uint32_t i = 0; i < resets.size(); i++) {
	    self.insert(resets[i]);
	    other.insert(eff.resets[i]);
	}
	return self == other;
    }
    return false;
}

varset_t Effect::writeVars() const {
    varset_t res;
    foreach (const IntAssignment* i, intassigns) {
	res += i->writeVars();
    } 
    foreach (const ClockReset* r, resets) {
	res += r->writeVars();
    }
    return res;
}

varset_t Effect::readVars() const {
    varset_t res;
    foreach (const IntAssignment* i, intassigns) {
	res += i->readVars();
    } 
    foreach (const ClockReset* r, resets) {
	res += r->readVars();
    }    
    return res;    
}

void Effect::apply(State* state) const {
    for (uint32_t i = 0; i < intassigns.size(); i++) {
	intassigns[i]->apply(state);
    }
    
    for (uint32_t i = 0; i < resets.size(); i++) {
	resets[i]->apply(state);
    }
}

ostream& Effect::display(ostream& o) const {
    if (intassigns.empty() && resets.empty()) {
	return o;
    }
    o << "assign ";
    printPtrVector(intassigns, ", ", o);
    if (!intassigns.empty() && !resets.empty()) {
	o << ", ";
    } 
    printPtrVector(resets, ", ", o);
    return o;
}
