Use separate containers for current and previous scopes

This patch introduces in ScopeBase separate containers
for declarations coming from the current scope and from
the previous scopes.
Until now, in one scope, all objects were kept in an stl map.
When a scope was created inside other scopes, a shallow
copy of the map was made. This solution was nice for
name shadowing (in new scopes, when a name was
encountered, the old objects were overridden by a new
one), but didn't allow for distinguishing where the objects
were allocated. As a result, it is impossible to know who
the owner is and who should delete them.

In this commit ScopeBase gets two containers: for old
and new objects. If a ScopeBase is made from another
ScopeBase object, all objects from the copied object
go to an old_XXX container, where XXX depends on the
type of the copied objects. When a ScopeBase object
is deleted, the objects from new_XXX are deleted and
the ones from old_XXX are not touched.

This patch adds some complexity to the internals
of ScopeBase, but leaves its interface unchanged.
This commit is contained in:
Pawel Szostek 2011-07-20 16:34:36 +02:00 committed by Stephen Williams
parent 3764216a88
commit a5ca9ea8be
4 changed files with 212 additions and 68 deletions

View File

@ -30,12 +30,16 @@ int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc)
{
int errors = 0;
for (map<perm_string,Signal*>::iterator cur = signals_.begin()
; cur != signals_.end() ; ++cur) {
for (map<perm_string,Signal*>::iterator cur = old_signals_.begin()
; cur != old_signals_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
}
for (map<perm_string,Signal*>::iterator cur = new_signals_.begin()
; cur != new_signals_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
}
return errors;
}
@ -43,12 +47,19 @@ int Architecture::emit(ostream&out, Entity*entity)
{
int errors = 0;
for (map<perm_string,struct const_t>::iterator cur = constants_.begin()
; cur != constants_.end() ; ++cur) {
for (map<perm_string,struct const_t*>::iterator cur = old_constants_.begin()
; cur != old_constants_.end() ; ++cur) {
out << "localparam " << cur->first << " = ";
errors += cur->second.val->emit(out, entity, this);
out << ";" << endl;
out << "localparam " << cur->first << " = ";
errors += cur->second->val->emit(out, entity, this);
out << ";" << endl;
}
for (map<perm_string,struct const_t*>::iterator cur = new_constants_.begin()
; cur != new_constants_.end() ; ++cur) {
out << "localparam " << cur->first << " = ";
errors += cur->second->val->emit(out, entity, this);
out << ";" << endl;
}
errors += emit_signals(out, entity, this);

View File

@ -79,36 +79,58 @@ void ComponentBase::dump_ports(ostream&out, int indent) const
void Scope::dump_scope(ostream&out) const
{
// Dump types
for (map<perm_string,const VType*>::const_iterator cur = types_.begin()
; cur != types_.end() ; ++cur) {
for (map<perm_string,const VType*>::const_iterator cur = old_types_.begin()
; cur != old_types_.end() ; ++cur) {
out << " " << cur->first << ": ";
cur->second->show(out);
out << endl;
}
for (map<perm_string,const VType*>::const_iterator cur = new_types_.begin()
; cur != new_types_.end() ; ++cur) {
out << " " << cur->first << ": ";
cur->second->show(out);
out << endl;
}
// Dump constants
for (map<perm_string,const_t>::const_iterator cur = constants_.begin()
; cur != constants_.end() ; ++cur) {
for (map<perm_string,const_t*>::const_iterator cur = old_constants_.begin()
; cur != old_constants_.end() ; ++cur) {
out << " constant " << cur->first << " = ";
out << endl;
}
// Dump signal declarations
for (map<perm_string,Signal*>::const_iterator cur = signals_.begin()
; cur != signals_.end() ; ++cur) {
if (cur->second)
cur->second->dump(out, 3);
else
out << " signal " << cur->first.str() << ": ???" << endl;
for (map<perm_string,const_t*>::const_iterator cur = new_constants_.begin()
; cur != new_constants_.end() ; ++cur) {
out << " constant " << cur->first << " = ";
out << endl;
}
// Dump signal declarations
for (map<perm_string,Signal*>::const_iterator cur = old_signals_.begin()
; cur != old_signals_.end() ; ++cur) {
if (cur->second)
cur->second->dump(out, 3);
else
out << " signal " << cur->first.str() << ": ???" << endl;
}
for (map<perm_string,Signal*>::const_iterator cur = new_signals_.begin()
; cur != new_signals_.end() ; ++cur) {
if (cur->second)
cur->second->dump(out, 3);
else
out << " signal " << cur->first.str() << ": ???" << endl;
}
// Dump component declarations
for (map<perm_string,ComponentBase*>::const_iterator cur = components_.begin()
; cur != components_.end() ; ++cur) {
for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin()
; cur != old_components_.end() ; ++cur) {
out << " component " << cur->first << " is" << endl;
cur->second->dump_ports(out);
out << " end component " << cur->first << endl;
}
for (map<perm_string,ComponentBase*>::const_iterator cur = new_components_.begin()
; cur != new_components_.end() ; ++cur) {
out << " component " << cur->first << " is" << endl;
cur->second->dump_ports(out);
out << " end component " << cur->first << endl;
}
}
void Entity::dump(ostream&out, int indent) const

View File

@ -18,61 +18,130 @@
*/
# include "scope.h"
# include <algorithm>
# include <iostream>
# include <iterator>
using namespace std;
ScopeBase::ScopeBase(const ScopeBase&ref)
{
constants_ = ref.constants_;
signals_ = ref.signals_;
components_ = ref.components_;
types_ = ref.types_;
merge(ref.old_constants_.begin(), ref.old_constants_.end(),
ref.new_constants_.begin(), ref.new_constants_.end(),
insert_iterator<map<perm_string, struct const_t*> >(
old_constants_, old_constants_.end())
);
merge(ref.old_signals_.begin(), ref.old_signals_.end(),
ref.new_signals_.begin(), ref.new_signals_.end(),
insert_iterator<map<perm_string, Signal*> >(
old_signals_, old_signals_.end())
);
merge(ref.old_components_.begin(), ref.old_components_.end(),
ref.new_components_.begin(), ref.new_components_.end(),
insert_iterator<map<perm_string, ComponentBase*> >(
old_components_, old_components_.end())
);
merge(ref.old_types_.begin(), ref.old_types_.end(),
ref.new_types_.begin(), ref.new_types_.end(),
insert_iterator<map<perm_string, const VType*> >(
old_types_, old_types_.end())
);
}
ScopeBase::~ScopeBase()
{
//freeing of member objects is performed by child classes
}
void ScopeBase::cleanup()
{
/*
* A parent scope is destroyed only if all child scopes
* were previously destroyed. There for we can delete all
* objects that were defined in this scope, leaving
* objects from the other scopes untouched.
*/
for(map<perm_string, Signal*>::iterator it = new_signals_.begin()
; it != new_signals_.end(); ++it)
delete it->second;
for(map<perm_string, ComponentBase*>::iterator it = new_components_.begin()
; it != new_components_.end(); ++it)
delete it->second;
for(map<perm_string, const VType*>::iterator it = new_types_.begin()
; it != new_types_.end(); ++it)
delete it->second;
for(map<perm_string, const_t*>::iterator it = new_constants_.begin()
; it != new_constants_.end(); ++it)
delete it->second;
}
const VType*ScopeBase::find_type(perm_string by_name)
{
map<perm_string,const VType*>::const_iterator cur = types_.find(by_name);
if (cur == types_.end())
return 0;
else
map<perm_string,const VType*>::const_iterator cur = new_types_.find(by_name);
if (cur == new_types_.end()) {
cur = old_types_.find(by_name);
if (cur == old_types_.end())
return 0;
else
return cur->second;
} else
return cur->second;
}
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp)
{
map<perm_string,const_t>::const_iterator cur = constants_.find(by_name);
if (cur == constants_.end())
return false;
typ = cur->second.typ;
exp = cur->second.val;
return true;
map<perm_string,struct const_t*>::const_iterator cur = new_constants_.find(by_name);
if (cur == new_constants_.end()) {
cur = old_constants_.find(by_name);
if (cur == old_constants_.end())
return false;
else {
typ = cur->second->typ;
exp = cur->second->val;
return true;
}
} else {
typ = cur->second->typ;
exp = cur->second->val;
return true;
}
}
void ScopeBase::do_use_from(const ScopeBase*that)
{
for (map<perm_string,ComponentBase*>::const_iterator cur = that->components_.begin()
; cur != that->components_.end() ; ++ cur) {
for (map<perm_string,ComponentBase*>::const_iterator cur = that->old_components_.begin()
; cur != that->old_components_.end() ; ++ cur) {
if (cur->second == 0)
continue;
components_[cur->first] = cur->second;
old_components_[cur->first] = cur->second;
}
for (map<perm_string,ComponentBase*>::const_iterator cur = that->new_components_.begin()
; cur != that->new_components_.end() ; ++ cur) {
if (cur->second == 0)
continue;
old_components_[cur->first] = cur->second;
}
for (map<perm_string,const VType*>::const_iterator cur = that->types_.begin()
; cur != that->types_.end() ; ++ cur) {
for (map<perm_string,const VType*>::const_iterator cur = that->old_types_.begin()
; cur != that->old_types_.end() ; ++ cur) {
if (cur->second == 0)
continue;
types_[cur->first] = cur->second;
old_types_[cur->first] = cur->second;
}
for (map<perm_string,const VType*>::const_iterator cur = that->new_types_.begin()
; cur != that->new_types_.end() ; ++ cur) {
if (cur->second == 0)
continue;
old_types_[cur->first] = cur->second;
}
for (map<perm_string,const_t>::const_iterator cur = that->constants_.begin()
; cur != that->constants_.end() ; ++ cur) {
constants_[cur->first] = cur->second;
for (map<perm_string,const_t*>::const_iterator cur = that->old_constants_.begin()
; cur != that->old_constants_.end() ; ++ cur) {
old_constants_[cur->first] = cur->second;
}
for (map<perm_string,const_t*>::const_iterator cur = that->new_constants_.begin()
; cur != that->new_constants_.end() ; ++ cur) {
old_constants_[cur->first] = cur->second;
}
}
@ -87,18 +156,27 @@ Scope::~Scope()
ComponentBase* Scope::find_component(perm_string by_name)
{
map<perm_string,ComponentBase*>::const_iterator cur = components_.find(by_name);
if (cur == components_.end())
return 0;
else
map<perm_string,ComponentBase*>::const_iterator cur = new_components_.find(by_name);
if (cur == new_components_.end()) {
cur = old_components_.find(by_name);
if (cur == old_components_.end())
return 0;
else
return cur->second;
} else
return cur->second;
}
Signal* Scope::find_signal(perm_string by_name)
{
map<perm_string,Signal*>::const_iterator cur = signals_.find(by_name);
if (cur == signals_.end())
return 0;
else
map<perm_string,Signal*>::const_iterator cur = new_signals_.find(by_name);
if (cur == new_signals_.end()) {
cur = old_signals_.find(by_name);
if (cur == old_signals_.end())
return 0;
else
return cur->second;
} else {
return cur->second;
}
}

View File

@ -22,12 +22,12 @@
# include <list>
# include <map>
# include "StringHeap.h"
# include "entity.h"
# include "expression.h"
# include "vsignal.h"
class Architecture;
class ComponentBase;
class Entity;
class Expression;
class Signal;
class VType;
class ScopeBase {
@ -40,18 +40,27 @@ class ScopeBase {
const VType* find_type(perm_string by_name);
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
protected:
void cleanup();
// Signal declarations...
std::map<perm_string,Signal*> signals_;
std::map<perm_string,Signal*> old_signals_; //previous scopes
std::map<perm_string,Signal*> new_signals_; //current scope
// Component declarations...
std::map<perm_string,ComponentBase*> components_;
std::map<perm_string,ComponentBase*> old_components_; //previous scopes
std::map<perm_string,ComponentBase*> new_components_; //current scope
// Type declarations...
std::map<perm_string,const VType*> types_;
std::map<perm_string,const VType*> old_types_; //previous scopes
std::map<perm_string,const VType*> new_types_; //current scope
// Constant declarations...
struct const_t {
~const_t() {delete typ; delete val;}
const_t(const VType*t, Expression* v) : typ(t), val(v) {};
const VType*typ;
Expression*val;
};
std::map<perm_string, struct const_t> constants_;
std::map<perm_string, struct const_t*> old_constants_; //previous scopes
std::map<perm_string, struct const_t*> new_constants_; //current scope
void do_use_from(const ScopeBase*that);
};
@ -90,20 +99,44 @@ class ActiveScope : public ScopeBase {
void use_from(const ScopeBase*that) { do_use_from(that); }
/* All bind_name function check if the given name was present
* in previous scopes. If it is found, it is erased (but the pointer
* is not freed), in order to implement name shadowing. The pointer
* be freed only in the scope where the object was defined. This is
* done in ScopeBase::cleanup() function .*/
void bind_name(perm_string name, Signal*obj)
{ signals_[name] = obj; }
{ map<perm_string, Signal*>::iterator it;
if((it = old_signals_.find(name)) != old_signals_.end() )
old_signals_.erase(it);
new_signals_[name] = obj;
}
void bind_name(perm_string name, ComponentBase*obj)
{ components_[name] = obj; }
{ map<perm_string, ComponentBase*>::iterator it;
if((it = old_components_.find(name)) != old_components_.end() )
old_components_.erase(it);
new_components_[name] = obj;
}
void bind_name(perm_string name, const VType*obj)
{ types_[name] = obj; }
void bind_name(perm_string name, const VType* t)
{ map<perm_string, const VType*>::iterator it;
if((it = old_types_.find(name)) != old_types_.end() )
old_types_.erase(it);
new_types_[name] = t;
}
void bind_name(perm_string name, const VType*obj, Expression*val)
{ map<perm_string, const_t*>::iterator it;
if((it = old_constants_.find(name)) != old_constants_.end() )
old_constants_.erase(it);
new_constants_[name] = new const_t(obj, val);
}
void destroy_global_scope()
{
const_t&tmp = constants_[name];
tmp.typ = obj;
tmp.val = val;
cleanup();
}
};