Handle default arguments in class new functions.

This commit is contained in:
Stephen Williams 2013-09-14 19:54:35 -07:00
parent 9a116498a2
commit 16414f921f
5 changed files with 86 additions and 32 deletions

View File

@ -26,6 +26,7 @@
# include <vector>
# include <list>
class Design;
class NetExpr;
class NetNet;
class NetScope;
class PWire;
@ -48,8 +49,12 @@ class PTaskFunc : public PScope, public LineInfo {
inline class_type_t* method_of() const { return this_type_; }
protected:
// Elaborate the ports list. Write into the ports vector the
// NetNet pointers for the ports, and write into the pdefs the
// default value expressions, if any.
void elaborate_sig_ports_(Design*des, NetScope*scope,
std::vector<NetNet*>&ports) const;
std::vector<NetNet*>&ports,
std::vector<NetExpr*>&pdefs) const;
void dump_ports_(std::ostream&out, unsigned ind) const;

View File

@ -4586,37 +4586,53 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
NetFuncDef*def = new_scope->func_def();
ivl_assert(*this, def);
if ((parms_.size()+1) != def->port_count()) {
// Are there too many arguments passed to the function. If so,
// generate an error message. The case of too few arguments
// will be handled below, when we run out of arguments.
if ((parms_.size()+1) > def->port_count()) {
cerr << get_fileline() << ": error: Parm count mismatch"
<< " passing " << parms_.size() << " arguments "
<< " to constructor expecting " << (def->port_count()-1)
<< " arguments." << endl;
des->errors += 1;
return obj;
}
vector<NetExpr*> parms (1 + parms_.size());
vector<NetExpr*> parms (def->port_count());
parms[0] = obj;
int missing_parms = 0;
int parm_errors = 0;
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
PExpr*tmp = parms_[idx];
size_t pidx = idx + 1;
for (size_t idx = 1 ; idx < parms.size() ; idx += 1) {
// While there are default arguments, check them.
if (idx <= parms_.size()) {
PExpr*tmp = parms_[idx-1];
if (tmp == 0) {
parms[pidx] = 0;
parms[idx] = 0;
missing_parms += 1;
continue;
}
parms[pidx] = elaborate_rval_expr(des, scope, def->port(pidx)->data_type(),
def->port(pidx)->vector_width(),
parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->data_type(),
def->port(idx)->vector_width(),
tmp, false);
if (parms[pidx] == 0) {
if (parms[idx] == 0)
parm_errors += 1;
continue;
}
// Ran out of explicit arguments. Is there a default
// argument we can use?
if (NetExpr*tmp = def->port_defe(idx)) {
parms[idx] = tmp;
continue;
}
// If we run out of passed expressions, and there is no
// default value for this port, then we will need to
// report an error that we are missing parameters.
missing_parms += 1;
parms[idx] = 0;
}
if (missing_parms > 0) {

View File

@ -596,10 +596,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
}
vector<NetNet*>ports;
elaborate_sig_ports_(des, scope, ports);
vector<NetExpr*>pdef;
elaborate_sig_ports_(des, scope, ports, pdef);
NetFuncDef*def = 0;
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports, pdef);
assert(def);
if (debug_elaborate)
@ -630,8 +631,9 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
elaborate_sig_wires_(des, scope);
vector<NetNet*>ports;
elaborate_sig_ports_(des, scope, ports);
NetTaskDef*def = new NetTaskDef(scope, ports);
vector<NetExpr*>pdefs;
elaborate_sig_ports_(des, scope, ports, pdefs);
NetTaskDef*def = new NetTaskDef(scope, ports, pdefs);
scope->set_task_def(def);
// Look for further signals in the sub-statement
@ -640,10 +642,11 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
}
void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
vector<NetNet*>&ports) const
vector<NetNet*>&ports, vector<NetExpr*>&pdefs) const
{
if (ports_ == 0) {
ports.clear();
pdefs.clear();
/* Make sure the function has at least one input
port. If it fails this test, print an error
@ -661,13 +664,16 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
}
ports.resize(ports_->size());
pdefs.resize(ports_->size());
for (size_t idx = 0 ; idx < ports_->size() ; idx += 1) {
perm_string port_name = ports_->at(idx).port->basename();
ports[idx] = 0;
pdefs[idx] = 0;
NetNet*tmp = scope->find_signal(port_name);
NetExpr*tmp_def = 0;
if (tmp == 0) {
cerr << get_fileline() << ": internal error: "
<< "task/function " << scope_path(scope)
@ -678,12 +684,19 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
continue;
}
// If the port has a default expression that can be used
// as a value when the caller doesn't bind, then
// elaborate that expression here. This expression
// should evaluate down do a constant.
if (ports_->at(idx).defe != 0) {
cerr << get_fileline() << ": sorry: "
<< "task/function default port expressions not supported."
<< endl;
tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe, -1, true);
if (tmp_def==0) {
cerr << get_fileline() << ": error: Unable to evaluate "
<< *ports_->at(idx).defe
<< " as a port default (constant) expression." << endl;
des->errors += 1;
}
}
if (tmp->port_type() == NetNet::NOT_A_PORT) {
cerr << get_fileline() << ": internal error: "
@ -696,11 +709,12 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
}
ports[idx] = tmp;
pdefs[idx] = tmp_def;
if (scope->type()==NetScope::FUNC && tmp->port_type()!=NetNet::PINPUT) {
cerr << tmp->get_fileline() << ": error: "
<< "Function " << scope_path(scope)
<< " port " << port_name
<< " is not an inputport." << endl;
<< " is not an input port." << endl;
cerr << tmp->get_fileline() << ": : "
<< "Function arguments must be input ports." << endl;
des->errors += 1;

View File

@ -2043,8 +2043,9 @@ verinum::V NetConst::value(unsigned idx) const
return value_[idx];
}
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po)
: scope_(s), statement_(0), result_sig_(result), ports_(po)
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po,
const vector<NetExpr*>&pd)
: scope_(s), statement_(0), result_sig_(result), ports_(po), pdefaults_(pd)
{
}
@ -2085,6 +2086,12 @@ const NetNet* NetFuncDef::port(unsigned idx) const
return ports_[idx];
}
NetExpr* NetFuncDef::port_defe(unsigned idx) const
{
assert(idx < pdefaults_.size());
return pdefaults_[idx];
}
const NetNet* NetFuncDef::return_sig() const
{
return result_sig_;
@ -2620,8 +2627,8 @@ unsigned NetUReduce::width() const
return width_;
}
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po)
: scope_(n), proc_(0), ports_(po)
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po, const vector<NetExpr*>&pd)
: scope_(n), proc_(0), ports_(po), pdefaults_(pd)
{
}
@ -2647,6 +2654,12 @@ NetNet* NetTaskDef::port(unsigned idx) const
return ports_[idx];
}
NetExpr* NetTaskDef::port_defe(unsigned idx) const
{
assert(idx < pdefaults_.size());
return pdefaults_[idx];
}
const NetScope* NetTaskDef::scope() const
{
return scope_;

View File

@ -3215,7 +3215,8 @@ class NetFree : public NetProc {
class NetFuncDef {
public:
NetFuncDef(NetScope*, NetNet*result, const std::vector<NetNet*>&po);
NetFuncDef(NetScope*, NetNet*result, const std::vector<NetNet*>&po,
const std::vector<NetExpr*>&pd);
~NetFuncDef();
void set_proc(NetProc*st);
@ -3227,6 +3228,7 @@ class NetFuncDef {
unsigned port_count() const;
const NetNet*port(unsigned idx) const;
NetExpr*port_defe(unsigned idx) const;
const NetNet*return_sig() const;
@ -3243,6 +3245,7 @@ class NetFuncDef {
NetProc*statement_;
NetNet*result_sig_;
std::vector<NetNet*>ports_;
std::vector<NetExpr*>pdefaults_;
};
/*
@ -3375,7 +3378,8 @@ class NetSTask : public NetProc {
class NetTaskDef {
public:
NetTaskDef(NetScope*n, const vector<NetNet*>&po);
NetTaskDef(NetScope*n, const vector<NetNet*>&po,
const std::vector<NetExpr*>&pd);
~NetTaskDef();
void set_proc(NetProc*p);
@ -3386,6 +3390,7 @@ class NetTaskDef {
unsigned port_count() const;
NetNet*port(unsigned idx) const;
NetExpr*port_defe(unsigned idx) const;
void dump(ostream&, unsigned) const;
DelayType delay_type() const;
@ -3393,7 +3398,8 @@ class NetTaskDef {
private:
NetScope*scope_;
NetProc*proc_;
vector<NetNet*>ports_;
std::vector<NetNet*>ports_;
std::vector<NetExpr*>pdefaults_; // Default expressions for ports.
private: // not implemented
NetTaskDef(const NetTaskDef&);