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

#include "component.h"
#include "location.h"
#include "resolver.h"
#include "variable.h"

#include "common/message.h"

#include <utap/expression.h>
#include <utap/type.h>

#include <cassert>

using namespace std;

void NameResolver::addChild(const Component* comp, Variable* var) {
    lookup.insert(make_pair(comp, ComponentVars())).first->second.children.push_back(var);
}

void NameResolver::addInteger(const Component* comp, Integer* integer) { addChild(comp, integer); }
void NameResolver::addClock(const Component* comp, Clock* clock) { addChild(comp, clock); }
void NameResolver::addChannel(const Component* comp, Channel* channel) { addChild(comp, channel); }
void NameResolver::addConstant(const Component* comp, Constant* constant) {
    addChild(comp, constant);
    lookup.insert(make_pair(comp, ComponentVars())).first->second.consts.push_back(constant);
}
void NameResolver::addLocation(const Component* comp, Location* loc) { addChild(comp, loc); }

Constant* NameResolver::findConst(const Component* comp, const UTAP::expression_t& expr) const {
    assert(expr.getType().isConstant());
    Constant* c = dynamic_cast<Constant*>(find(comp, expr.toString()));
    if (c) {
	return c;
    }
    if (comp->parent) {
	return findConst(comp->parent, expr);
    }
    error() << "cannot find " << expr.toString() << endl;
    return NULL;
}

Variable* NameResolver::find(const Component* comp, const std::string& name) const {
    lookup_t::const_iterator it = lookup.find(comp);
    if (it == lookup.end()) {
	return NULL;
    }
    const ComponentVars& cv = it->second;
    
    for (uint32_t i = 0; i < cv.children.size(); i++) {
//	cout << "comp " << name << " " << cv.children[i]->name << endl;
	if (name == cv.children[i]->name) {
	    return cv.children[i];
	}
    }
    return NULL;
    
}

Variable* NameResolver::getChild(const Component* comp, uint32_t index) const {
    return lookup.find(comp)->second.children[index];
}

ostream& NameResolver::ComponentVars::display(ostream& o) const {
    for (uint32_t i = 0; i < children.size(); i++) {
	o << "    " << children[i]->name << endl;
    }
    return o;
}

ostream& NameResolver::display(ostream& o) const {
    for (lookup_t::const_iterator it = lookup.begin(); it != lookup.end(); ++it) {
	o << it->first->name << endl;
	it->second.display(o);
	o << endl;
    }
    return o;
}

