From a5ca9ea8be6cb19cfea79e88f287f1f2fbe46d81 Mon Sep 17 00:00:00 2001 From: Pawel Szostek Date: Wed, 20 Jul 2011 16:34:36 +0200 Subject: [PATCH] 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. --- vhdlpp/architec_emit.cc | 25 +++++-- vhdlpp/debug.cc | 52 ++++++++++----- vhdlpp/scope.cc | 142 +++++++++++++++++++++++++++++++--------- vhdlpp/scope.h | 61 +++++++++++++---- 4 files changed, 212 insertions(+), 68 deletions(-) diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index ce60631af..1305426ab 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -30,12 +30,16 @@ int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc) { int errors = 0; - for (map::iterator cur = signals_.begin() - ; cur != signals_.end() ; ++cur) { + for (map::iterator cur = old_signals_.begin() + ; cur != old_signals_.end() ; ++cur) { errors += cur->second->emit(out, entity, arc); } + for (map::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::iterator cur = constants_.begin() - ; cur != constants_.end() ; ++cur) { + for (map::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::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); diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 0847f11a3..54fac14d8 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -79,36 +79,58 @@ void ComponentBase::dump_ports(ostream&out, int indent) const void Scope::dump_scope(ostream&out) const { // Dump types - for (map::const_iterator cur = types_.begin() - ; cur != types_.end() ; ++cur) { + for (map::const_iterator cur = old_types_.begin() + ; cur != old_types_.end() ; ++cur) { out << " " << cur->first << ": "; cur->second->show(out); out << endl; } + for (map::const_iterator cur = new_types_.begin() + ; cur != new_types_.end() ; ++cur) { + out << " " << cur->first << ": "; + cur->second->show(out); + out << endl; + } // Dump constants - for (map::const_iterator cur = constants_.begin() - ; cur != constants_.end() ; ++cur) { + for (map::const_iterator cur = old_constants_.begin() + ; cur != old_constants_.end() ; ++cur) { out << " constant " << cur->first << " = "; out << endl; } - - // Dump signal declarations - for (map::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::const_iterator cur = new_constants_.begin() + ; cur != new_constants_.end() ; ++cur) { + out << " constant " << cur->first << " = "; + out << endl; + } + // Dump signal declarations + for (map::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::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::const_iterator cur = components_.begin() - ; cur != components_.end() ; ++cur) { + for (map::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::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 diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 6f2da84b9..a715e86f4 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -18,61 +18,130 @@ */ # include "scope.h" +# include # include +# include 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 >( + old_constants_, old_constants_.end()) + ); + merge(ref.old_signals_.begin(), ref.old_signals_.end(), + ref.new_signals_.begin(), ref.new_signals_.end(), + insert_iterator >( + old_signals_, old_signals_.end()) + ); + merge(ref.old_components_.begin(), ref.old_components_.end(), + ref.new_components_.begin(), ref.new_components_.end(), + insert_iterator >( + old_components_, old_components_.end()) + ); + merge(ref.old_types_.begin(), ref.old_types_.end(), + ref.new_types_.begin(), ref.new_types_.end(), + insert_iterator >( + 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::iterator it = new_signals_.begin() + ; it != new_signals_.end(); ++it) + delete it->second; + for(map::iterator it = new_components_.begin() + ; it != new_components_.end(); ++it) + delete it->second; + for(map::iterator it = new_types_.begin() + ; it != new_types_.end(); ++it) + delete it->second; + for(map::iterator it = new_constants_.begin() + ; it != new_constants_.end(); ++it) + delete it->second; } const VType*ScopeBase::find_type(perm_string by_name) { - map::const_iterator cur = types_.find(by_name); - if (cur == types_.end()) - return 0; - else + map::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::const_iterator cur = constants_.find(by_name); - if (cur == constants_.end()) - return false; - - typ = cur->second.typ; - exp = cur->second.val; - return true; + map::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::const_iterator cur = that->components_.begin() - ; cur != that->components_.end() ; ++ cur) { + for (map::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::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::const_iterator cur = that->types_.begin() - ; cur != that->types_.end() ; ++ cur) { + for (map::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::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::const_iterator cur = that->constants_.begin() - ; cur != that->constants_.end() ; ++ cur) { - constants_[cur->first] = cur->second; + for (map::const_iterator cur = that->old_constants_.begin() + ; cur != that->old_constants_.end() ; ++ cur) { + old_constants_[cur->first] = cur->second; + } + for (map::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::const_iterator cur = components_.find(by_name); - if (cur == components_.end()) - return 0; - else + map::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::const_iterator cur = signals_.find(by_name); - if (cur == signals_.end()) - return 0; - else + map::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; + } } diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index fd5e80272..c17f7932b 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -22,12 +22,12 @@ # include # include # 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 signals_; + std::map old_signals_; //previous scopes + std::map new_signals_; //current scope // Component declarations... - std::map components_; + std::map old_components_; //previous scopes + std::map new_components_; //current scope // Type declarations... - std::map types_; + std::map old_types_; //previous scopes + std::map 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 constants_; + std::map old_constants_; //previous scopes + std::map 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::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::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::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::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(); } };