Chain class instance constructors with arguments.
This commit is contained in:
parent
0157a156fb
commit
d192f545ac
|
|
@ -20,7 +20,7 @@
|
||||||
# include "PClass.h"
|
# include "PClass.h"
|
||||||
|
|
||||||
PClass::PClass(perm_string name, LexicalScope*parent)
|
PClass::PClass(perm_string name, LexicalScope*parent)
|
||||||
: PScopeExtra(name, parent)
|
: PScopeExtra(name, parent), type(0), chain(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
3
PClass.h
3
PClass.h
|
|
@ -24,6 +24,8 @@
|
||||||
# include "StringHeap.h"
|
# include "StringHeap.h"
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
||||||
|
class PChainConstructor;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SystemVerilog supports class declarations with their own lexical
|
* SystemVerilog supports class declarations with their own lexical
|
||||||
* scope, etc. The parser arranges for these to be created and
|
* scope, etc. The parser arranges for these to be created and
|
||||||
|
|
@ -40,6 +42,7 @@ class PClass : public PScopeExtra, public LineInfo {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class_type_t*type;
|
class_type_t*type;
|
||||||
|
PChainConstructor*chain;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
3
PExpr.h
3
PExpr.h
|
|
@ -558,7 +558,8 @@ class PENewClass : public PExpr {
|
||||||
private:
|
private:
|
||||||
NetExpr* elaborate_expr_constructor_(Design*des, NetScope*scope,
|
NetExpr* elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||||
const netclass_t*ctype,
|
const netclass_t*ctype,
|
||||||
NetExpr*obj, unsigned flags) const;
|
NetExpr*obj, unsigned flags,
|
||||||
|
const netclass_t*derived) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<PExpr*>parms_;
|
std::vector<PExpr*>parms_;
|
||||||
|
|
|
||||||
15
PFunction.cc
15
PFunction.cc
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
# include "PTask.h"
|
# include "PTask.h"
|
||||||
|
# include "Statement.h"
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
|
|
||||||
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
|
PFunction::PFunction(perm_string name, LexicalScope*parent, bool is_auto__)
|
||||||
|
|
@ -43,3 +44,17 @@ void PFunction::set_return(const data_type_t*t)
|
||||||
{
|
{
|
||||||
return_type_ = t;
|
return_type_ = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PChainConstructor* PFunction::extract_chain_constructor()
|
||||||
|
{
|
||||||
|
PChainConstructor*res = 0;
|
||||||
|
|
||||||
|
if (res = dynamic_cast<PChainConstructor*> (statement_)) {
|
||||||
|
statement_ = 0;
|
||||||
|
|
||||||
|
} else if (PBlock*blk = dynamic_cast<PBlock*>(statement_)) {
|
||||||
|
res = blk->extract_chain_constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
|
||||||
6
PTask.h
6
PTask.h
|
|
@ -29,6 +29,7 @@ class Design;
|
||||||
class NetExpr;
|
class NetExpr;
|
||||||
class NetNet;
|
class NetNet;
|
||||||
class NetScope;
|
class NetScope;
|
||||||
|
class PChainConstructor;
|
||||||
class PWire;
|
class PWire;
|
||||||
class Statement;
|
class Statement;
|
||||||
class PExpr;
|
class PExpr;
|
||||||
|
|
@ -117,6 +118,11 @@ class PFunction : public PTaskFunc {
|
||||||
|
|
||||||
inline Statement* get_statement() { return statement_; }
|
inline Statement* get_statement() { return statement_; }
|
||||||
|
|
||||||
|
// This is only used if this function is a constructor. In
|
||||||
|
// that case, this method looks for a PChainConstructor in the
|
||||||
|
// statement and extracts it if found.
|
||||||
|
PChainConstructor*extract_chain_constructor();
|
||||||
|
|
||||||
void elaborate_scope(Design*des, NetScope*scope) const;
|
void elaborate_scope(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
/* elaborate the ports and return value. */
|
/* elaborate the ports and return value. */
|
||||||
|
|
|
||||||
30
Statement.cc
30
Statement.cc
|
|
@ -115,6 +115,21 @@ PBlock::~PBlock()
|
||||||
delete list_[idx];
|
delete list_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PChainConstructor* PBlock::extract_chain_constructor()
|
||||||
|
{
|
||||||
|
if (list_.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (PChainConstructor*res = dynamic_cast<PChainConstructor*> (list_[0])) {
|
||||||
|
for (size_t idx = 0 ; idx < list_.size()-1 ; idx += 1)
|
||||||
|
list_[idx] = list_[idx+1];
|
||||||
|
list_.resize(list_.size()-1);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void PBlock::set_join_type(PBlock::BL_TYPE type)
|
void PBlock::set_join_type(PBlock::BL_TYPE type)
|
||||||
{
|
{
|
||||||
assert(bl_type_ == BL_PAR);
|
assert(bl_type_ == BL_PAR);
|
||||||
|
|
@ -206,6 +221,21 @@ PCAssign::~PCAssign()
|
||||||
delete expr_;
|
delete expr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PChainConstructor::PChainConstructor(const list<PExpr*>&parms)
|
||||||
|
: parms_(parms.size())
|
||||||
|
{
|
||||||
|
list<PExpr*>::const_iterator cur = parms.begin();
|
||||||
|
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||||
|
parms_[idx] = *cur;
|
||||||
|
++cur;
|
||||||
|
}
|
||||||
|
assert(cur == parms.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
PChainConstructor::~PChainConstructor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PCondit::PCondit(PExpr*ex, Statement*i, Statement*e)
|
PCondit::PCondit(PExpr*ex, Statement*i, Statement*e)
|
||||||
: expr_(ex), if_(i), else_(e)
|
: expr_(ex), if_(i), else_(e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
25
Statement.h
25
Statement.h
|
|
@ -31,6 +31,7 @@
|
||||||
# include "HName.h"
|
# include "HName.h"
|
||||||
# include "LineInfo.h"
|
# include "LineInfo.h"
|
||||||
class PExpr;
|
class PExpr;
|
||||||
|
class PChainConstructor;
|
||||||
class PPackage;
|
class PPackage;
|
||||||
class Statement;
|
class Statement;
|
||||||
class PEventStatement;
|
class PEventStatement;
|
||||||
|
|
@ -181,6 +182,11 @@ class PBlock : public PScope, public Statement {
|
||||||
|
|
||||||
BL_TYPE bl_type() const { return bl_type_; }
|
BL_TYPE bl_type() const { return bl_type_; }
|
||||||
|
|
||||||
|
// This is only used if this block is the statement list for a
|
||||||
|
// constructor. We look for a PChainConstructor as the first
|
||||||
|
// statement, and if it is there, extract it.
|
||||||
|
PChainConstructor*extract_chain_constructor();
|
||||||
|
|
||||||
// If the bl_type() is BL_PAR, it is possible to replace it
|
// If the bl_type() is BL_PAR, it is possible to replace it
|
||||||
// with JOIN_NONE or JOIN_ANY. This is to help the parser.
|
// with JOIN_NONE or JOIN_ANY. This is to help the parser.
|
||||||
void set_join_type(BL_TYPE);
|
void set_join_type(BL_TYPE);
|
||||||
|
|
@ -272,6 +278,25 @@ class PCAssign : public Statement {
|
||||||
PExpr*expr_;
|
PExpr*expr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This represents the syntax "super.new(...)". This is not really an
|
||||||
|
* executable statement, but the elaborator will handle these
|
||||||
|
* specially and will remove them from the statement stream. If any
|
||||||
|
*/
|
||||||
|
class PChainConstructor : public Statement {
|
||||||
|
public:
|
||||||
|
PChainConstructor(const list<PExpr*>&parms);
|
||||||
|
~PChainConstructor();
|
||||||
|
|
||||||
|
virtual void dump(ostream&out, unsigned ind) const;
|
||||||
|
|
||||||
|
inline const std::vector<PExpr*>& chain_args(void) const
|
||||||
|
{ return parms_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<PExpr*> parms_;
|
||||||
|
};
|
||||||
|
|
||||||
class PCondit : public Statement {
|
class PCondit : public Statement {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
35
elab_expr.cc
35
elab_expr.cc
|
|
@ -4679,13 +4679,21 @@ unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&)
|
||||||
* This elaborates the constructor for a class. This arranges for the
|
* This elaborates the constructor for a class. This arranges for the
|
||||||
* call of parent class constructors, if present, and also
|
* call of parent class constructors, if present, and also
|
||||||
* initializers in front of an explicit constructor.
|
* initializers in front of an explicit constructor.
|
||||||
|
*
|
||||||
|
* The derived argument is the type of the class derived from the
|
||||||
|
* current one. This is used to get chained constructor arguments, if necessary.
|
||||||
*/
|
*/
|
||||||
NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||||
const netclass_t*ctype,
|
const netclass_t*ctype,
|
||||||
NetExpr*obj, unsigned flags) const
|
NetExpr*obj, unsigned flags,
|
||||||
|
const netclass_t*derived) const
|
||||||
{
|
{
|
||||||
|
// If there is a super-class, then call the super-class
|
||||||
|
// constructors first. The results of the current class
|
||||||
|
// constructors cannot effect the superclass, so this is the
|
||||||
|
// right order of events.
|
||||||
if (const netclass_t*super_class = ctype->get_super()) {
|
if (const netclass_t*super_class = ctype->get_super()) {
|
||||||
obj = elaborate_expr_constructor_(des, scope, super_class, obj, flags);
|
obj = elaborate_expr_constructor_(des, scope, super_class, obj, flags, ctype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4710,10 +4718,18 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||||
obj = tmp;
|
obj = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The parameters for the constructor are the arguments of the
|
||||||
|
// new(...) expression, unless we are recursing, in which case
|
||||||
|
// we use the chained arguments. Note that the arguments to
|
||||||
|
// the chained constructor must be elaborated in the scope of
|
||||||
|
// the subclass (so that arguments can be passed down) so also
|
||||||
|
// select which scope we are going to use.
|
||||||
|
const vector<PExpr*>&use_parms = derived? derived->get_chain_args() : parms_;
|
||||||
|
|
||||||
NetScope*new_scope = ctype->method_from_name(perm_string::literal("new"));
|
NetScope*new_scope = ctype->method_from_name(perm_string::literal("new"));
|
||||||
if (new_scope == 0) {
|
if (new_scope == 0) {
|
||||||
// No constructor.
|
// No constructor.
|
||||||
if (parms_.size() > 0) {
|
if (use_parms.size() > 0) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
<< "Class " << ctype->get_name()
|
<< "Class " << ctype->get_name()
|
||||||
<< " has no constructor, but you passed " << parms_.size()
|
<< " has no constructor, but you passed " << parms_.size()
|
||||||
|
|
@ -4730,9 +4746,9 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||||
// Are there too many arguments passed to the function. If so,
|
// Are there too many arguments passed to the function. If so,
|
||||||
// generate an error message. The case of too few arguments
|
// generate an error message. The case of too few arguments
|
||||||
// will be handled below, when we run out of arguments.
|
// will be handled below, when we run out of arguments.
|
||||||
if ((parms_.size()+1) > def->port_count()) {
|
if ((use_parms.size()+1) > def->port_count()) {
|
||||||
cerr << get_fileline() << ": error: Parm count mismatch"
|
cerr << get_fileline() << ": error: Parm count mismatch"
|
||||||
<< " passing " << parms_.size() << " arguments "
|
<< " passing " << use_parms.size() << " arguments "
|
||||||
<< " to constructor expecting " << (def->port_count()-1)
|
<< " to constructor expecting " << (def->port_count()-1)
|
||||||
<< " arguments." << endl;
|
<< " arguments." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
|
|
@ -4745,9 +4761,10 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||||
int parm_errors = 0;
|
int parm_errors = 0;
|
||||||
for (size_t idx = 1 ; idx < parms.size() ; idx += 1) {
|
for (size_t idx = 1 ; idx < parms.size() ; idx += 1) {
|
||||||
// While there are default arguments, check them.
|
// While there are default arguments, check them.
|
||||||
if (idx <= parms_.size() && parms_[idx-1]) {
|
if (idx <= use_parms.size() && use_parms[idx-1]) {
|
||||||
PExpr*tmp = parms_[idx-1];
|
PExpr*tmp = use_parms[idx-1];
|
||||||
parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->net_type(),
|
parms[idx] = elaborate_rval_expr(des, scope,
|
||||||
|
def->port(idx)->net_type(),
|
||||||
def->port(idx)->data_type(),
|
def->port(idx)->data_type(),
|
||||||
def->port(idx)->vector_width(),
|
def->port(idx)->vector_width(),
|
||||||
tmp, false);
|
tmp, false);
|
||||||
|
|
@ -4801,7 +4818,7 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
||||||
// allocation alone.
|
// allocation alone.
|
||||||
const netclass_t*ctype = dynamic_cast<const netclass_t*> (ntype);
|
const netclass_t*ctype = dynamic_cast<const netclass_t*> (ntype);
|
||||||
|
|
||||||
obj = elaborate_expr_constructor_(des, scope, ctype, obj, flags);
|
obj = elaborate_expr_constructor_(des, scope, ctype, obj, flags, 0);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,12 @@ static void blend_class_constructors(PClass*pclass)
|
||||||
if (iter_new == pclass->funcs.end())
|
if (iter_new == pclass->funcs.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// While we're here, look for a super.new() call. If we find
|
||||||
|
// it, strip it out of the constructor and set it aside for
|
||||||
|
// when we actually call the chained constructor.
|
||||||
|
pclass->chain = iter_new->second->extract_chain_constructor();
|
||||||
|
|
||||||
|
|
||||||
map<perm_string,PFunction*>::iterator iter_new2 = pclass->funcs.find(new2);
|
map<perm_string,PFunction*>::iterator iter_new2 = pclass->funcs.find(new2);
|
||||||
if (iter_new2 == pclass->funcs.end())
|
if (iter_new2 == pclass->funcs.end())
|
||||||
return;
|
return;
|
||||||
|
|
@ -374,7 +380,10 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
|
const static vector<PExpr*>no_args;
|
||||||
|
const vector<PExpr*>&use_chain_args = (pclass&&pclass->chain)? pclass->chain->chain_args() : no_args;
|
||||||
|
|
||||||
|
netclass_t*use_class = new netclass_t(use_type->name, use_base_class, use_chain_args);
|
||||||
|
|
||||||
// Class scopes have no parent scope, because references are
|
// Class scopes have no parent scope, because references are
|
||||||
// not allowed to escape a class method.
|
// not allowed to escape a class method.
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
netclass_t::netclass_t(perm_string name, netclass_t*sup)
|
netclass_t::netclass_t(perm_string name, netclass_t*sup, const vector<PExpr*>&chain_args)
|
||||||
: name_(name), super_(sup), class_scope_(0)
|
: name_(name), super_(sup), chain_args_(chain_args), class_scope_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
netclass.h
10
netclass.h
|
|
@ -30,10 +30,11 @@ class Design;
|
||||||
class NetNet;
|
class NetNet;
|
||||||
class NetScope;
|
class NetScope;
|
||||||
class PClass;
|
class PClass;
|
||||||
|
class PExpr;
|
||||||
|
|
||||||
class netclass_t : public ivl_type_s {
|
class netclass_t : public ivl_type_s {
|
||||||
public:
|
public:
|
||||||
netclass_t(perm_string class_name, netclass_t*par);
|
netclass_t(perm_string class_name, netclass_t*par, const vector<PExpr*>&pchain_args);
|
||||||
~netclass_t();
|
~netclass_t();
|
||||||
|
|
||||||
// Set the property of the class during elaboration. Set the
|
// Set the property of the class during elaboration. Set the
|
||||||
|
|
@ -45,6 +46,9 @@ class netclass_t : public ivl_type_s {
|
||||||
// is used for the elaboration of methods (tasks/functions).
|
// is used for the elaboration of methods (tasks/functions).
|
||||||
void set_class_scope(NetScope*cscope);
|
void set_class_scope(NetScope*cscope);
|
||||||
|
|
||||||
|
inline const std::vector<PExpr*>& get_chain_args(void) const
|
||||||
|
{ return chain_args_; }
|
||||||
|
|
||||||
// As an ivl_type_s object, the netclass is always an
|
// As an ivl_type_s object, the netclass is always an
|
||||||
// ivl_VT_CLASS object.
|
// ivl_VT_CLASS object.
|
||||||
ivl_variable_type_t base_type() const;
|
ivl_variable_type_t base_type() const;
|
||||||
|
|
@ -99,8 +103,10 @@ class netclass_t : public ivl_type_s {
|
||||||
private:
|
private:
|
||||||
perm_string name_;
|
perm_string name_;
|
||||||
// If this is derived from another base class, point to it
|
// If this is derived from another base class, point to it
|
||||||
// here.
|
// here. The super constructor may take arguments, and the
|
||||||
|
// chain_parms_ are those arguments.
|
||||||
netclass_t*super_;
|
netclass_t*super_;
|
||||||
|
std::vector<PExpr*> chain_args_;
|
||||||
// Map properrty names to property table index.
|
// Map properrty names to property table index.
|
||||||
std::map<perm_string,size_t> properties_;
|
std::map<perm_string,size_t> properties_;
|
||||||
// Vector of properties.
|
// Vector of properties.
|
||||||
|
|
|
||||||
6
parse.y
6
parse.y
|
|
@ -5853,9 +5853,9 @@ statement_item /* This is roughly statement_item in the LRM */
|
||||||
out. */
|
out. */
|
||||||
|
|
||||||
| implicit_class_handle '.' K_new '(' expression_list_with_nuls ')' ';'
|
| implicit_class_handle '.' K_new '(' expression_list_with_nuls ')' ';'
|
||||||
{ yyerror(@1, "sorry: Calls to superclass constructor not supported.");
|
{ PChainConstructor*tmp = new PChainConstructor(*$5);
|
||||||
yyerrok;
|
FILE_NAME(tmp, @3);
|
||||||
$$ = new PNoop;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| hierarchy_identifier '(' error ')' ';'
|
| hierarchy_identifier '(' error ')' ';'
|
||||||
{ yyerror(@3, "error: Syntax error in task arguments.");
|
{ yyerror(@3, "error: Syntax error in task arguments.");
|
||||||
|
|
|
||||||
|
|
@ -821,6 +821,19 @@ void PCase::dump(ostream&out, unsigned ind) const
|
||||||
out << setw(ind) << "" << "endcase" << endl;
|
out << setw(ind) << "" << "endcase" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PChainConstructor::dump(ostream&out, unsigned ind) const
|
||||||
|
{
|
||||||
|
out << setw(ind) << "" << "super.new(";
|
||||||
|
if (parms_.size() > 0) {
|
||||||
|
if (parms_[0]) out << *parms_[0];
|
||||||
|
}
|
||||||
|
for (size_t idx = 1 ; idx < parms_.size() ; idx += 1) {
|
||||||
|
out << ", ";
|
||||||
|
if (parms_[idx]) out << *parms_[idx];
|
||||||
|
}
|
||||||
|
out << ");" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void PCondit::dump(ostream&out, unsigned ind) const
|
void PCondit::dump(ostream&out, unsigned ind) const
|
||||||
{
|
{
|
||||||
out << setw(ind) << "" << "if (" << *expr_ << ")" << endl;
|
out << setw(ind) << "" << "if (" << *expr_ << ")" << endl;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue