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-24 09:53:06 -07:00
committed by Stephen Williams
parent 3764216a88
commit a5ca9ea8be
4 changed files with 212 additions and 68 deletions
+47 -14
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();
}
};