Blend implicit constructor with explicit constructor

Class types that have both implicit construction and
an explicit constructor can blend the implicit and
explicit construction into the "new" function defined
by the user. This doesn't change the behavior any, but
removes a function call and related scope.
This commit is contained in:
Stephen Williams 2013-06-24 16:42:28 -04:00
parent 637d43fb5a
commit 046535cfbb
4 changed files with 75 additions and 3 deletions

View File

@ -110,6 +110,8 @@ class PFunction : public PTaskFunc {
void set_statement(Statement *s);
void set_return(const data_type_t*t);
inline Statement* get_statement() { return statement_; }
void elaborate_scope(Design*des, NetScope*scope) const;
/* elaborate the ports and return value. */

View File

@ -21,6 +21,7 @@
# include "Statement.h"
# include "PExpr.h"
# include "ivl_assert.h"
Statement::~Statement()
{
@ -126,6 +127,17 @@ void PBlock::set_statement(const vector<Statement*>&st)
list_ = st;
}
void PBlock::push_statement_front(Statement*that)
{
ivl_assert(*this, bl_type_==BL_SEQ);
list_.resize(list_.size()+1);
for (size_t idx = list_.size()-1 ; idx > 0 ; idx -= 1)
list_[idx] = list_[idx-1];
list_[0] = that;
}
PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
: package_(0), path_(n), parms_(p.size())
{

View File

@ -186,6 +186,10 @@ class PBlock : public PScope, public Statement {
void set_statement(const std::vector<Statement*>&st);
// Copy the statement from that block to the front of this
// block.
void push_statement_front(Statement*that);
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;

View File

@ -293,8 +293,60 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
}
}
static void elaborate_scope_class(Design*des, NetScope*scope,
PClass*pclass)
/*
* If the pclass includes an implicit and explicit constructor, then
* merge the implicit constructor into the explicit constructor as
* statements in the beginning.
*
* This is not necessary for proper functionality, it is an
* optimization, so we can easily give up if it doesn't seem like it
* will obviously work.
*/
static void blend_class_constructors(PClass*pclass)
{
perm_string new1 = perm_string::literal("new");
perm_string new2 = perm_string::literal("new@");
map<perm_string,PFunction*>::iterator iter_new = pclass->funcs.find(new1);
if (iter_new == pclass->funcs.end())
return;
map<perm_string,PFunction*>::iterator iter_new2 = pclass->funcs.find(new2);
if (iter_new2 == pclass->funcs.end())
return;
PFunction*use_new = iter_new->second;
PFunction*use_new2 = iter_new2->second;
// These constructors must be methods of the same class.
ivl_assert(*use_new, use_new->method_of() == use_new2->method_of());
Statement*def_new = use_new->get_statement();
Statement*def_new2 = use_new2->get_statement();
// If either constructor has no definition, then give up. This
// might happen, for example, during parse errors or other
// degenerate situations.
if (def_new==0 || def_new2==0)
return;
PBlock*blk_new = dynamic_cast<PBlock*> (def_new);
// For now, only do this if the functions are defined by
// statement blocks. That should be true by definition for
// implicit constructors, and common for explicit constructors.
if (blk_new==0)
return;
ivl_assert(*blk_new, blk_new ->bl_type()==PBlock::BL_SEQ);
blk_new->push_statement_front(def_new2);
pclass->funcs.erase(iter_new2);
delete use_new2;
}
static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
{
class_type_t*use_type = pclass->type;
netclass_t*use_class = new netclass_t(use_type->name);
@ -367,8 +419,10 @@ static void elaborate_scope_class(Design*des, NetScope*scope,
static void elaborate_scope_classes(Design*des, NetScope*scope,
const vector<PClass*>&classes)
{
for (size_t idx = 0 ; idx < classes.size() ; idx += 1)
for (size_t idx = 0 ; idx < classes.size() ; idx += 1) {
blend_class_constructors(classes[idx]);
elaborate_scope_class(des, scope, classes[idx]);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,