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;
|
int errors = 0;
|
||||||
|
|
||||||
for (map<perm_string,Signal*>::iterator cur = signals_.begin()
|
for (map<perm_string,Signal*>::iterator cur = old_signals_.begin()
|
||||||
; cur != signals_.end() ; ++cur) {
|
; cur != old_signals_.end() ; ++cur) {
|
||||||
|
|
||||||
errors += cur->second->emit(out, entity, arc);
|
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;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,12 +47,19 @@ int Architecture::emit(ostream&out, Entity*entity)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
for (map<perm_string,struct const_t>::iterator cur = constants_.begin()
|
for (map<perm_string,struct const_t*>::iterator cur = old_constants_.begin()
|
||||||
; cur != constants_.end() ; ++cur) {
|
; cur != old_constants_.end() ; ++cur) {
|
||||||
|
|
||||||
out << "localparam " << cur->first << " = ";
|
out << "localparam " << cur->first << " = ";
|
||||||
errors += cur->second.val->emit(out, entity, this);
|
errors += cur->second->val->emit(out, entity, this);
|
||||||
out << ";" << endl;
|
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);
|
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
|
void Scope::dump_scope(ostream&out) const
|
||||||
{
|
{
|
||||||
// Dump types
|
// Dump types
|
||||||
for (map<perm_string,const VType*>::const_iterator cur = types_.begin()
|
for (map<perm_string,const VType*>::const_iterator cur = old_types_.begin()
|
||||||
; cur != types_.end() ; ++cur) {
|
; cur != old_types_.end() ; ++cur) {
|
||||||
out << " " << cur->first << ": ";
|
out << " " << cur->first << ": ";
|
||||||
cur->second->show(out);
|
cur->second->show(out);
|
||||||
out << endl;
|
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
|
// Dump constants
|
||||||
for (map<perm_string,const_t>::const_iterator cur = constants_.begin()
|
for (map<perm_string,const_t*>::const_iterator cur = old_constants_.begin()
|
||||||
; cur != constants_.end() ; ++cur) {
|
; cur != old_constants_.end() ; ++cur) {
|
||||||
out << " constant " << cur->first << " = ";
|
out << " constant " << cur->first << " = ";
|
||||||
out << endl;
|
out << endl;
|
||||||
}
|
}
|
||||||
|
for (map<perm_string,const_t*>::const_iterator cur = new_constants_.begin()
|
||||||
// Dump signal declarations
|
; cur != new_constants_.end() ; ++cur) {
|
||||||
for (map<perm_string,Signal*>::const_iterator cur = signals_.begin()
|
out << " constant " << cur->first << " = ";
|
||||||
; cur != signals_.end() ; ++cur) {
|
out << endl;
|
||||||
if (cur->second)
|
}
|
||||||
cur->second->dump(out, 3);
|
// Dump signal declarations
|
||||||
else
|
for (map<perm_string,Signal*>::const_iterator cur = old_signals_.begin()
|
||||||
out << " signal " << cur->first.str() << ": ???" << endl;
|
; 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
|
// Dump component declarations
|
||||||
for (map<perm_string,ComponentBase*>::const_iterator cur = components_.begin()
|
for (map<perm_string,ComponentBase*>::const_iterator cur = old_components_.begin()
|
||||||
; cur != components_.end() ; ++cur) {
|
; cur != old_components_.end() ; ++cur) {
|
||||||
out << " component " << cur->first << " is" << endl;
|
out << " component " << cur->first << " is" << endl;
|
||||||
cur->second->dump_ports(out);
|
cur->second->dump_ports(out);
|
||||||
out << " end component " << cur->first << endl;
|
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
|
void Entity::dump(ostream&out, int indent) const
|
||||||
|
|
|
||||||
142
vhdlpp/scope.cc
142
vhdlpp/scope.cc
|
|
@ -18,61 +18,130 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# include "scope.h"
|
# include "scope.h"
|
||||||
|
# include <algorithm>
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
# include <iterator>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
ScopeBase::ScopeBase(const ScopeBase&ref)
|
ScopeBase::ScopeBase(const ScopeBase&ref)
|
||||||
{
|
{
|
||||||
constants_ = ref.constants_;
|
merge(ref.old_constants_.begin(), ref.old_constants_.end(),
|
||||||
signals_ = ref.signals_;
|
ref.new_constants_.begin(), ref.new_constants_.end(),
|
||||||
components_ = ref.components_;
|
insert_iterator<map<perm_string, struct const_t*> >(
|
||||||
types_ = ref.types_;
|
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()
|
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)
|
const VType*ScopeBase::find_type(perm_string by_name)
|
||||||
{
|
{
|
||||||
map<perm_string,const VType*>::const_iterator cur = types_.find(by_name);
|
map<perm_string,const VType*>::const_iterator cur = new_types_.find(by_name);
|
||||||
if (cur == types_.end())
|
if (cur == new_types_.end()) {
|
||||||
return 0;
|
cur = old_types_.find(by_name);
|
||||||
else
|
if (cur == old_types_.end())
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return cur->second;
|
||||||
|
} else
|
||||||
return cur->second;
|
return cur->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp)
|
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);
|
map<perm_string,struct const_t*>::const_iterator cur = new_constants_.find(by_name);
|
||||||
if (cur == constants_.end())
|
if (cur == new_constants_.end()) {
|
||||||
return false;
|
cur = old_constants_.find(by_name);
|
||||||
|
if (cur == old_constants_.end())
|
||||||
typ = cur->second.typ;
|
return false;
|
||||||
exp = cur->second.val;
|
else {
|
||||||
return true;
|
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)
|
void ScopeBase::do_use_from(const ScopeBase*that)
|
||||||
{
|
{
|
||||||
for (map<perm_string,ComponentBase*>::const_iterator cur = that->components_.begin()
|
for (map<perm_string,ComponentBase*>::const_iterator cur = that->old_components_.begin()
|
||||||
; cur != that->components_.end() ; ++ cur) {
|
; cur != that->old_components_.end() ; ++ cur) {
|
||||||
if (cur->second == 0)
|
if (cur->second == 0)
|
||||||
continue;
|
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()
|
for (map<perm_string,const VType*>::const_iterator cur = that->old_types_.begin()
|
||||||
; cur != that->types_.end() ; ++ cur) {
|
; cur != that->old_types_.end() ; ++ cur) {
|
||||||
if (cur->second == 0)
|
if (cur->second == 0)
|
||||||
continue;
|
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()
|
for (map<perm_string,const_t*>::const_iterator cur = that->old_constants_.begin()
|
||||||
; cur != that->constants_.end() ; ++ cur) {
|
; cur != that->old_constants_.end() ; ++ cur) {
|
||||||
constants_[cur->first] = cur->second;
|
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)
|
ComponentBase* Scope::find_component(perm_string by_name)
|
||||||
{
|
{
|
||||||
map<perm_string,ComponentBase*>::const_iterator cur = components_.find(by_name);
|
map<perm_string,ComponentBase*>::const_iterator cur = new_components_.find(by_name);
|
||||||
if (cur == components_.end())
|
if (cur == new_components_.end()) {
|
||||||
return 0;
|
cur = old_components_.find(by_name);
|
||||||
else
|
if (cur == old_components_.end())
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return cur->second;
|
||||||
|
} else
|
||||||
return cur->second;
|
return cur->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
Signal* Scope::find_signal(perm_string by_name)
|
Signal* Scope::find_signal(perm_string by_name)
|
||||||
{
|
{
|
||||||
map<perm_string,Signal*>::const_iterator cur = signals_.find(by_name);
|
map<perm_string,Signal*>::const_iterator cur = new_signals_.find(by_name);
|
||||||
if (cur == signals_.end())
|
if (cur == new_signals_.end()) {
|
||||||
return 0;
|
cur = old_signals_.find(by_name);
|
||||||
else
|
if (cur == old_signals_.end())
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return cur->second;
|
||||||
|
} else {
|
||||||
return cur->second;
|
return cur->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@
|
||||||
# include <list>
|
# include <list>
|
||||||
# include <map>
|
# include <map>
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
|
# include "entity.h"
|
||||||
|
# include "expression.h"
|
||||||
|
# include "vsignal.h"
|
||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
class ComponentBase;
|
class ComponentBase;
|
||||||
class Entity;
|
|
||||||
class Expression;
|
|
||||||
class Signal;
|
|
||||||
class VType;
|
class VType;
|
||||||
|
|
||||||
class ScopeBase {
|
class ScopeBase {
|
||||||
|
|
@ -40,18 +40,27 @@ class ScopeBase {
|
||||||
const VType* find_type(perm_string by_name);
|
const VType* find_type(perm_string by_name);
|
||||||
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
|
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
|
||||||
protected:
|
protected:
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
// Signal declarations...
|
// 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...
|
// 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...
|
// 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...
|
// Constant declarations...
|
||||||
struct const_t {
|
struct const_t {
|
||||||
|
~const_t() {delete typ; delete val;}
|
||||||
|
const_t(const VType*t, Expression* v) : typ(t), val(v) {};
|
||||||
|
|
||||||
const VType*typ;
|
const VType*typ;
|
||||||
Expression*val;
|
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);
|
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); }
|
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)
|
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)
|
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)
|
void bind_name(perm_string name, const VType* t)
|
||||||
{ types_[name] = obj; }
|
{ 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)
|
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];
|
cleanup();
|
||||||
tmp.typ = obj;
|
|
||||||
tmp.val = val;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue