2011-04-14 03:30:00 +02:00
|
|
|
/*
|
2016-03-25 07:41:34 +01:00
|
|
|
* Copyright (c) 2011-2016 Stephen Williams (steve@icarus.com)
|
2013-06-08 00:47:14 +02:00
|
|
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
2011-04-14 03:30:00 +02:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2011-04-14 03:30:00 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "scope.h"
|
2013-05-19 02:36:29 +02:00
|
|
|
# include "package.h"
|
2014-09-29 11:31:18 +02:00
|
|
|
# include "subprogram.h"
|
2015-01-26 11:14:31 +01:00
|
|
|
# include "entity.h"
|
2015-06-10 18:41:51 +02:00
|
|
|
# include "std_funcs.h"
|
2015-06-12 14:18:41 +02:00
|
|
|
# include "std_types.h"
|
2016-02-24 10:14:50 +01:00
|
|
|
# include "compiler.h"
|
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.
2011-07-20 16:34:36 +02:00
|
|
|
# include <algorithm>
|
2011-04-18 02:19:09 +02:00
|
|
|
# include <iostream>
|
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.
2011-07-20 16:34:36 +02:00
|
|
|
# include <iterator>
|
2016-02-24 10:14:50 +01:00
|
|
|
# include <cstdio>
|
|
|
|
|
# include <cstring>
|
2013-05-19 02:36:29 +02:00
|
|
|
# include <cassert>
|
2016-02-24 10:14:50 +01:00
|
|
|
# include <StringHeap.h>
|
2011-04-14 03:30:00 +02:00
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
2016-02-24 10:14:50 +01:00
|
|
|
static int scope_counter = 0;
|
|
|
|
|
|
2013-05-13 04:17:12 +02:00
|
|
|
ScopeBase::ScopeBase(const ActiveScope&ref)
|
2016-02-24 10:14:50 +01:00
|
|
|
: old_signals_(ref.old_signals_), new_signals_(ref.new_signals_),
|
|
|
|
|
old_variables_(ref.old_variables_), new_variables_(ref.new_variables_),
|
|
|
|
|
old_components_(ref.old_components_), new_components_(ref.new_components_),
|
|
|
|
|
use_types_(ref.use_types_), cur_types_(ref.cur_types_),
|
|
|
|
|
use_constants_(ref.use_constants_), cur_constants_(ref.cur_constants_),
|
|
|
|
|
use_subprograms_(ref.use_subprograms_), cur_subprograms_(ref.cur_subprograms_),
|
|
|
|
|
scopes_(ref.scopes_), use_enums_(ref.use_enums_),
|
|
|
|
|
initializers_(ref.initializers_), finalizers_(ref.finalizers_),
|
2016-03-25 07:41:34 +01:00
|
|
|
package_header_(ref.package_header_), name_(ref.name_)
|
2011-04-14 03:30:00 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
ScopeBase::~ScopeBase()
|
2011-04-14 03:30:00 +02:00
|
|
|
{
|
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.
2011-07-20 16:34:36 +02:00
|
|
|
//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.
|
|
|
|
|
*/
|
2011-07-21 11:04:48 +02:00
|
|
|
delete_all(new_signals_);
|
2016-01-06 09:38:34 +01:00
|
|
|
delete_all(new_variables_);
|
2011-07-21 11:04:48 +02:00
|
|
|
delete_all(new_components_);
|
2013-05-13 04:17:12 +02:00
|
|
|
delete_all(cur_types_);
|
|
|
|
|
delete_all(cur_constants_);
|
2016-01-29 16:34:10 +01:00
|
|
|
for (map<perm_string,SubHeaderList>::iterator cur = cur_subprograms_.begin()
|
|
|
|
|
; cur != cur_subprograms_.end() ; ++cur) {
|
|
|
|
|
delete_all(cur->second);
|
|
|
|
|
}
|
2011-04-14 03:30:00 +02:00
|
|
|
}
|
|
|
|
|
|
2016-02-24 10:14:50 +01:00
|
|
|
ScopeBase*ScopeBase::find_scope(perm_string name) const
|
|
|
|
|
{
|
|
|
|
|
map<perm_string, ScopeBase*>::const_iterator it = scopes_.find(name);
|
|
|
|
|
|
|
|
|
|
if(it != scopes_.end())
|
|
|
|
|
return it->second;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
const VType*ScopeBase::find_type(perm_string by_name)
|
2011-04-14 03:30:00 +02:00
|
|
|
{
|
2013-05-13 04:17:12 +02:00
|
|
|
map<perm_string,const VType*>::const_iterator cur = cur_types_.find(by_name);
|
|
|
|
|
if (cur == cur_types_.end()) {
|
|
|
|
|
cur = use_types_.find(by_name);
|
|
|
|
|
if (cur == use_types_.end())
|
2015-08-27 14:13:58 +02:00
|
|
|
return NULL; // nothing found
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cur->second;
|
2011-04-14 03:30:00 +02:00
|
|
|
}
|
2011-04-14 04:55:18 +02:00
|
|
|
|
2015-02-16 12:06:33 +01:00
|
|
|
bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const
|
2011-04-18 02:19:09 +02:00
|
|
|
{
|
2015-02-19 17:01:14 +01:00
|
|
|
typ = NULL;
|
|
|
|
|
exp = NULL;
|
|
|
|
|
|
2013-05-13 04:17:12 +02:00
|
|
|
map<perm_string,struct const_t*>::const_iterator cur = cur_constants_.find(by_name);
|
|
|
|
|
if (cur == cur_constants_.end()) {
|
|
|
|
|
cur = use_constants_.find(by_name);
|
|
|
|
|
if (cur == use_constants_.end())
|
2015-08-27 14:13:58 +02:00
|
|
|
return false; // nothing found
|
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.
2011-07-20 16:34:36 +02:00
|
|
|
}
|
2015-02-19 17:01:14 +01:00
|
|
|
|
2015-08-27 14:13:58 +02:00
|
|
|
typ = cur->second->typ;
|
|
|
|
|
exp = cur->second->val;
|
|
|
|
|
return true;
|
2011-04-18 02:19:09 +02:00
|
|
|
}
|
|
|
|
|
|
2011-08-29 00:30:45 +02:00
|
|
|
Signal* ScopeBase::find_signal(perm_string by_name) const
|
|
|
|
|
{
|
|
|
|
|
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())
|
2015-08-27 14:13:58 +02:00
|
|
|
return NULL; // nothing found
|
2011-08-29 00:30:45 +02:00
|
|
|
}
|
2015-08-27 14:13:58 +02:00
|
|
|
|
|
|
|
|
return cur->second;
|
2011-08-29 00:30:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Variable* ScopeBase::find_variable(perm_string by_name) const
|
|
|
|
|
{
|
|
|
|
|
map<perm_string,Variable*>::const_iterator cur = new_variables_.find(by_name);
|
|
|
|
|
if (cur == new_variables_.end()) {
|
|
|
|
|
cur = old_variables_.find(by_name);
|
|
|
|
|
if (cur == old_variables_.end())
|
2015-08-27 14:13:58 +02:00
|
|
|
return 0; // nothing found
|
2011-08-29 00:30:45 +02:00
|
|
|
}
|
2015-08-27 14:13:58 +02:00
|
|
|
|
|
|
|
|
return cur->second;
|
2011-08-29 00:30:45 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-22 14:03:59 +02:00
|
|
|
const InterfacePort* ScopeBase::find_param(perm_string) const
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const InterfacePort* ScopeBase::find_param_all(perm_string by_name) const
|
2015-01-26 11:14:31 +01:00
|
|
|
{
|
2016-01-29 16:34:10 +01:00
|
|
|
for(map<perm_string,SubHeaderList>::const_iterator cur = use_subprograms_.begin();
|
|
|
|
|
cur != use_subprograms_.end(); ++cur) {
|
|
|
|
|
const SubHeaderList& subp_list = cur->second;
|
|
|
|
|
|
|
|
|
|
for(SubHeaderList::const_iterator it = subp_list.begin();
|
|
|
|
|
it != subp_list.end(); ++it) {
|
|
|
|
|
if(const InterfacePort*port = (*it)->find_param(by_name))
|
|
|
|
|
return port;
|
|
|
|
|
}
|
2015-01-26 11:14:31 +01:00
|
|
|
}
|
|
|
|
|
|
2016-01-29 16:34:10 +01:00
|
|
|
for(map<perm_string,SubHeaderList>::const_iterator cur = cur_subprograms_.begin();
|
|
|
|
|
cur != cur_subprograms_.end(); ++cur) {
|
|
|
|
|
const SubHeaderList& subp_list = cur->second;
|
|
|
|
|
|
|
|
|
|
for(SubHeaderList::const_iterator it = subp_list.begin();
|
|
|
|
|
it != subp_list.end(); ++it) {
|
|
|
|
|
if(const InterfacePort*port = (*it)->find_param(by_name))
|
|
|
|
|
return port;
|
|
|
|
|
}
|
2015-01-26 11:14:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-29 16:34:10 +01:00
|
|
|
SubHeaderList ScopeBase::find_subprogram(perm_string name) const
|
2013-05-19 02:36:29 +02:00
|
|
|
{
|
2016-01-29 16:34:10 +01:00
|
|
|
map<perm_string,SubHeaderList>::const_iterator cur;
|
2013-05-19 02:36:29 +02:00
|
|
|
|
|
|
|
|
cur = cur_subprograms_.find(name);
|
|
|
|
|
if (cur != cur_subprograms_.end())
|
2016-01-29 16:34:10 +01:00
|
|
|
return cur->second;
|
2013-05-19 02:36:29 +02:00
|
|
|
|
|
|
|
|
cur = use_subprograms_.find(name);
|
2013-06-08 00:47:14 +02:00
|
|
|
if (cur != use_subprograms_.end())
|
2016-01-29 16:34:10 +01:00
|
|
|
return cur->second;
|
2013-05-19 02:36:29 +02:00
|
|
|
|
2015-06-10 18:41:51 +02:00
|
|
|
return find_std_subprogram(name);
|
2013-05-19 02:36:29 +02:00
|
|
|
}
|
|
|
|
|
|
2015-05-07 14:42:31 +02:00
|
|
|
const VTypeEnum* ScopeBase::is_enum_name(perm_string name) const
|
2015-02-06 10:44:22 +01:00
|
|
|
{
|
|
|
|
|
for(list<const VTypeEnum*>::const_iterator it = use_enums_.begin();
|
|
|
|
|
it != use_enums_.end(); ++it) {
|
|
|
|
|
if((*it)->has_name(name))
|
2015-05-07 14:42:31 +02:00
|
|
|
return *it;
|
2015-02-06 10:44:22 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-12 14:18:41 +02:00
|
|
|
return find_std_enum_name(name);
|
2015-02-06 10:44:22 +01:00
|
|
|
}
|
|
|
|
|
|
2013-05-13 04:17:12 +02:00
|
|
|
/*
|
|
|
|
|
* This method is only used by the ActiveScope derived class to import
|
|
|
|
|
* definition from another scope.
|
|
|
|
|
*/
|
2011-04-18 02:19:09 +02:00
|
|
|
void ScopeBase::do_use_from(const ScopeBase*that)
|
2011-04-14 04:55:18 +02:00
|
|
|
{
|
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.
2011-07-20 16:34:36 +02:00
|
|
|
for (map<perm_string,ComponentBase*>::const_iterator cur = that->old_components_.begin()
|
|
|
|
|
; cur != that->old_components_.end() ; ++ cur) {
|
2011-04-14 04:55:18 +02:00
|
|
|
if (cur->second == 0)
|
|
|
|
|
continue;
|
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.
2011-07-20 16:34:36 +02:00
|
|
|
old_components_[cur->first] = cur->second;
|
|
|
|
|
}
|
2013-05-06 04:05:46 +02:00
|
|
|
for (map<perm_string,ComponentBase*>::const_iterator cur = that->new_components_.begin()
|
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.
2011-07-20 16:34:36 +02:00
|
|
|
; cur != that->new_components_.end() ; ++ cur) {
|
|
|
|
|
if (cur->second == 0)
|
|
|
|
|
continue;
|
|
|
|
|
old_components_[cur->first] = cur->second;
|
2011-04-14 04:55:18 +02:00
|
|
|
}
|
2011-04-18 02:19:09 +02:00
|
|
|
|
2016-01-29 16:34:10 +01:00
|
|
|
for (map<perm_string,SubHeaderList>::const_iterator cur = that->cur_subprograms_.begin()
|
2013-05-19 02:36:29 +02:00
|
|
|
; cur != that->cur_subprograms_.end() ; ++ cur) {
|
2016-01-29 16:34:10 +01:00
|
|
|
if (cur->second.empty())
|
2013-05-06 04:05:46 +02:00
|
|
|
continue;
|
2013-05-19 02:36:29 +02:00
|
|
|
use_subprograms_[cur->first] = cur->second;
|
2013-05-06 04:05:46 +02:00
|
|
|
}
|
|
|
|
|
|
2013-05-13 04:17:12 +02:00
|
|
|
for (map<perm_string,const VType*>::const_iterator cur = that->cur_types_.begin()
|
|
|
|
|
; cur != that->cur_types_.end() ; ++ cur) {
|
2011-04-18 02:19:09 +02:00
|
|
|
if (cur->second == 0)
|
|
|
|
|
continue;
|
2013-05-13 04:17:12 +02:00
|
|
|
use_types_[cur->first] = cur->second;
|
2011-04-18 02:19:09 +02:00
|
|
|
}
|
|
|
|
|
|
2013-05-13 04:17:12 +02:00
|
|
|
for (map<perm_string,const_t*>::const_iterator cur = that->cur_constants_.begin()
|
|
|
|
|
; cur != that->cur_constants_.end() ; ++ cur) {
|
|
|
|
|
use_constants_[cur->first] = cur->second;
|
2011-04-18 02:19:09 +02:00
|
|
|
}
|
2015-02-06 10:44:22 +01:00
|
|
|
|
|
|
|
|
use_enums_ = that->use_enums_;
|
2011-04-18 02:19:09 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-31 10:46:24 +02:00
|
|
|
void ScopeBase::transfer_from(ScopeBase&ref, transfer_type_t what)
|
2014-09-29 11:38:54 +02:00
|
|
|
{
|
2015-03-31 10:46:24 +02:00
|
|
|
if(what & SIGNALS) {
|
|
|
|
|
std::copy(ref.new_signals_.begin(), ref.new_signals_.end(),
|
|
|
|
|
insert_iterator<map<perm_string, Signal*> >(
|
|
|
|
|
new_signals_, new_signals_.end())
|
|
|
|
|
);
|
|
|
|
|
ref.new_signals_.clear();
|
|
|
|
|
}
|
2014-09-29 11:38:54 +02:00
|
|
|
|
2015-03-31 10:46:24 +02:00
|
|
|
if(what & VARIABLES) {
|
|
|
|
|
std::copy(ref.new_variables_.begin(), ref.new_variables_.end(),
|
|
|
|
|
insert_iterator<map<perm_string, Variable*> >(
|
|
|
|
|
new_variables_, new_variables_.end())
|
|
|
|
|
);
|
|
|
|
|
ref.new_variables_.clear();
|
|
|
|
|
}
|
2014-09-29 11:38:54 +02:00
|
|
|
|
2015-03-31 10:46:24 +02:00
|
|
|
if(what & COMPONENTS) {
|
|
|
|
|
std::copy(ref.new_components_.begin(), ref.new_components_.end(),
|
|
|
|
|
insert_iterator<map<perm_string, ComponentBase*> >(
|
|
|
|
|
new_components_, new_components_.end())
|
|
|
|
|
);
|
|
|
|
|
ref.new_components_.clear();
|
|
|
|
|
}
|
2014-09-29 11:38:54 +02:00
|
|
|
}
|
|
|
|
|
|
2016-01-29 16:34:10 +01:00
|
|
|
SubprogramHeader*ScopeBase::match_subprogram(perm_string name,
|
|
|
|
|
const list<const VType*>*params) const
|
|
|
|
|
{
|
|
|
|
|
int req_param_count = params ? params->size() : 0;
|
|
|
|
|
|
|
|
|
|
// Find all subprograms with matching name
|
|
|
|
|
SubHeaderList l = find_std_subprogram(name);
|
|
|
|
|
map<perm_string,SubHeaderList>::const_iterator cur;
|
|
|
|
|
|
|
|
|
|
cur = use_subprograms_.find(name);
|
|
|
|
|
if (cur != use_subprograms_.end())
|
|
|
|
|
copy(cur->second.begin(), cur->second.end(),
|
|
|
|
|
front_insert_iterator<SubHeaderList>(l));
|
|
|
|
|
|
|
|
|
|
cur = cur_subprograms_.find(name);
|
|
|
|
|
if(cur != cur_subprograms_.end())
|
|
|
|
|
copy(cur->second.begin(), cur->second.end(),
|
|
|
|
|
front_insert_iterator<SubHeaderList>(l));
|
|
|
|
|
|
|
|
|
|
// Find the matching one
|
|
|
|
|
for(SubHeaderList::iterator it = l.begin(); it != l.end(); ++it) {
|
|
|
|
|
SubprogramHeader*subp = *it;
|
|
|
|
|
|
|
|
|
|
if(req_param_count != subp->param_count())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Do not check the return type here, it might depend on the arguments
|
|
|
|
|
|
|
|
|
|
if(params) {
|
|
|
|
|
list<const VType*>::const_iterator p = params->begin();
|
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < req_param_count; ++i) {
|
|
|
|
|
const VType*param_type = subp->peek_param_type(i);
|
|
|
|
|
|
|
|
|
|
if(*p && param_type && !param_type->type_match(*p)) {
|
|
|
|
|
ok = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!ok)
|
|
|
|
|
continue; // check another function
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Yay, we have a match!
|
|
|
|
|
return subp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-24 10:14:50 +01:00
|
|
|
void ScopeBase::generate_name()
|
2013-05-19 02:36:29 +02:00
|
|
|
{
|
2016-02-24 10:14:50 +01:00
|
|
|
char buf[64];
|
|
|
|
|
|
|
|
|
|
// Generate a name for the scope
|
|
|
|
|
snprintf(buf, sizeof(buf), "__scope_%d", scope_counter++);
|
|
|
|
|
name_ = gen_strings.make(buf);
|
2013-05-19 02:36:29 +02:00
|
|
|
}
|
|
|
|
|
|
2016-01-29 16:34:10 +01:00
|
|
|
SubprogramHeader* ActiveScope::recall_subprogram(const SubprogramHeader*subp) const
|
2013-05-19 02:36:29 +02:00
|
|
|
{
|
2016-01-29 16:34:10 +01:00
|
|
|
list<const VType*> arg_types;
|
|
|
|
|
SubprogramHeader*tmp;
|
2013-05-19 02:36:29 +02:00
|
|
|
|
2016-01-29 16:34:10 +01:00
|
|
|
for(int i = 0; i < subp->param_count(); ++i)
|
|
|
|
|
arg_types.push_back(subp->peek_param_type(i));
|
|
|
|
|
|
|
|
|
|
if ((tmp = match_subprogram(subp->name(), &arg_types))) {
|
|
|
|
|
assert(!tmp->body());
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
2013-05-19 02:36:29 +02:00
|
|
|
|
2016-01-29 16:34:10 +01:00
|
|
|
if (package_header_) {
|
|
|
|
|
tmp = package_header_->match_subprogram(subp->name(), &arg_types);
|
|
|
|
|
assert(!tmp || !tmp->body());
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
2013-05-19 02:36:29 +02:00
|
|
|
}
|
|
|
|
|
|
2011-08-29 00:30:45 +02:00
|
|
|
bool ActiveScope::is_vector_name(perm_string name) const
|
|
|
|
|
{
|
|
|
|
|
if (find_signal(name))
|
|
|
|
|
return true;
|
|
|
|
|
if (find_variable(name))
|
|
|
|
|
return true;
|
|
|
|
|
|
2015-02-16 12:06:33 +01:00
|
|
|
const VType*dummy_type;
|
|
|
|
|
Expression*dummy_exp;
|
|
|
|
|
if (find_constant(name, dummy_type, dummy_exp))
|
|
|
|
|
return true;
|
|
|
|
|
|
2011-09-12 00:28:58 +02:00
|
|
|
if (context_entity_ && context_entity_->find_port(name))
|
|
|
|
|
return true;
|
|
|
|
|
|
2011-08-29 00:30:45 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-18 02:19:09 +02:00
|
|
|
ComponentBase* Scope::find_component(perm_string by_name)
|
|
|
|
|
{
|
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.
2011-07-20 16:34:36 +02:00
|
|
|
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
|
2011-04-18 02:19:09 +02:00
|
|
|
return cur->second;
|
2011-04-14 04:55:18 +02:00
|
|
|
}
|
2016-02-24 10:14:50 +01:00
|
|
|
|
|
|
|
|
ActiveScope::ActiveScope(const ActiveScope*par)
|
|
|
|
|
: ScopeBase(*par), context_entity_(par->context_entity_)
|
|
|
|
|
{
|
|
|
|
|
generate_name();
|
|
|
|
|
|
|
|
|
|
// Move all the objects available in higher level scopes to use*/old* maps.
|
|
|
|
|
// This way we can store the new items in now empty cur*/new* maps.
|
|
|
|
|
merge(par->old_signals_.begin(), par->old_signals_.end(),
|
|
|
|
|
par->new_signals_.begin(), par->new_signals_.end(),
|
|
|
|
|
insert_iterator<map<perm_string, Signal*> >(
|
|
|
|
|
old_signals_, old_signals_.end())
|
|
|
|
|
);
|
|
|
|
|
merge(par->old_variables_.begin(), par->old_variables_.end(),
|
|
|
|
|
par->new_variables_.begin(), par->new_variables_.end(),
|
|
|
|
|
insert_iterator<map<perm_string, Variable*> >(
|
|
|
|
|
old_variables_, old_variables_.end())
|
|
|
|
|
);
|
|
|
|
|
merge(par->old_components_.begin(), par->old_components_.end(),
|
|
|
|
|
par->new_components_.begin(), par->new_components_.end(),
|
|
|
|
|
insert_iterator<map<perm_string, ComponentBase*> >(
|
|
|
|
|
old_components_, old_components_.end())
|
|
|
|
|
);
|
|
|
|
|
merge(par->use_types_.begin(), par->use_types_.end(),
|
|
|
|
|
par->cur_types_.begin(), par->cur_types_.end(),
|
|
|
|
|
insert_iterator<map<perm_string, const VType*> >(
|
|
|
|
|
use_types_, use_types_.end())
|
|
|
|
|
);
|
|
|
|
|
merge(par->use_subprograms_.begin(), par->use_subprograms_.end(),
|
|
|
|
|
par->cur_subprograms_.begin(), par->cur_subprograms_.end(),
|
|
|
|
|
insert_iterator<map<perm_string, SubHeaderList> >(
|
|
|
|
|
use_subprograms_, use_subprograms_.end())
|
|
|
|
|
);
|
|
|
|
|
}
|