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:
parent
3764216a88
commit
a5ca9ea8be
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
142
vhdlpp/scope.cc
142
vhdlpp/scope.cc
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue