Handle array assignment patters through pform.
This gets us to elaboration. In the process also fix up ivl_type_t type comparisons to do deep type comparison.
This commit is contained in:
parent
2355e1ed8e
commit
18c338ad09
19
PExpr.cc
19
PExpr.cc
|
|
@ -94,6 +94,25 @@ const char* PExpr::width_mode_name(width_mode_t mode)
|
|||
}
|
||||
}
|
||||
|
||||
PEAssignPattern::PEAssignPattern()
|
||||
{
|
||||
}
|
||||
|
||||
PEAssignPattern::PEAssignPattern(const list<PExpr*>&p)
|
||||
: parms_(p.size())
|
||||
{
|
||||
size_t idx = 0;
|
||||
for (list<PExpr*>::const_iterator cur = p.begin()
|
||||
; cur != p.end() ; ++cur) {
|
||||
parms_[idx] = *cur;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
PEAssignPattern::~PEAssignPattern()
|
||||
{
|
||||
}
|
||||
|
||||
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
|
||||
: op_(op), left_(l), right_(r)
|
||||
{
|
||||
|
|
|
|||
20
PExpr.h
20
PExpr.h
|
|
@ -194,6 +194,26 @@ class PExpr : public LineInfo {
|
|||
|
||||
ostream& operator << (ostream&, const PExpr&);
|
||||
|
||||
class PEAssignPattern : public PExpr {
|
||||
public:
|
||||
explicit PEAssignPattern();
|
||||
explicit PEAssignPattern(const std::list<PExpr*>&p);
|
||||
~PEAssignPattern();
|
||||
|
||||
void dump(std::ostream&) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope, width_mode_t&mode);
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
||||
private:
|
||||
std::vector<PExpr*>parms_;
|
||||
};
|
||||
|
||||
class PEConcat : public PExpr {
|
||||
|
||||
public:
|
||||
|
|
|
|||
80
elab_expr.cc
80
elab_expr.cc
|
|
@ -86,15 +86,34 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type, unsigned lv_width,
|
||||
PExpr*expr, bool need_const)
|
||||
{
|
||||
if (debug_elaborate) {
|
||||
cerr << expr->get_fileline() << ": elaborate_rval_expr: "
|
||||
<< "expr=" << *expr;
|
||||
if (lv_net_type)
|
||||
cerr << ", lv_net_type=" << *lv_net_type;
|
||||
else
|
||||
cerr << ", lv_net_type=<nil>";
|
||||
|
||||
cerr << ", lv_type=" << lv_type
|
||||
<< ", lv_width=" << lv_width
|
||||
<< endl;
|
||||
}
|
||||
|
||||
int context_wid = -1;
|
||||
switch (lv_type) {
|
||||
case IVL_VT_DARRAY:
|
||||
// For these types, use a different elab_and_eval that
|
||||
// uses the lv_net_type. We should eventually transition
|
||||
// all the types to this new form.
|
||||
if (lv_net_type)
|
||||
return elab_and_eval(des, scope, expr, lv_net_type, need_const);
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
case IVL_VT_STRING:
|
||||
case IVL_VT_DARRAY:
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
|
|
@ -163,6 +182,42 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For now, assuse that assignment patterns are for dynamic
|
||||
* objects. This is not really true as this expression type, fully
|
||||
* supported, can assign to packed arrays and structs, unpacked arrays
|
||||
* and dynamic arrays.
|
||||
*/
|
||||
unsigned PEAssignPattern::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
{
|
||||
expr_type_ = IVL_VT_DARRAY;
|
||||
expr_width_ = 1;
|
||||
min_width_ = 1;
|
||||
signed_flag_= false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t ntype, unsigned flags) const
|
||||
{
|
||||
cerr << get_fileline() << ": sorry: I don't know how to elaborate "
|
||||
<< "assignment_pattern expressions yet." << endl;
|
||||
cerr << get_fileline() << ": : Expression is: " << *this
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* PEAssignPattern::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
|
||||
{
|
||||
cerr << get_fileline() << ": sorry: I do not know how to"
|
||||
<< " elaborate assignment patterns using old method." << endl;
|
||||
cerr << get_fileline() << ": : Expression is: " << *this
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
ivl_assert(*this, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
{
|
||||
|
|
@ -1524,7 +1579,8 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
// Process the method argument if it is available.
|
||||
NetExpr* count = 0;
|
||||
if (args != 0 && parg) {
|
||||
count = elaborate_rval_expr(des, scope, IVL_VT_BOOL, 32, parg);
|
||||
count = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
|
||||
IVL_VT_BOOL, 32, parg);
|
||||
if (count == 0) {
|
||||
cerr << li->get_fileline() << ": error: unable to elaborate "
|
||||
"enumeration method argument " << use_path << "."
|
||||
|
|
@ -1978,7 +2034,7 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
|
|||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::elaborate_base_: "
|
||||
<< "Expecting " << parms_count
|
||||
<< " for function " << scope_path(dscope) << "." << endl;
|
||||
<< " argument for function " << scope_path(dscope) << "." << endl;
|
||||
}
|
||||
|
||||
/* Elaborate the input expressions for the function. This is
|
||||
|
|
@ -2061,6 +2117,7 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
|||
PExpr*tmp = parms_[idx];
|
||||
if (tmp) {
|
||||
parms[pidx] = elaborate_rval_expr(des, scope,
|
||||
def->port(pidx)->net_type(),
|
||||
def->port(pidx)->data_type(),
|
||||
(unsigned)def->port(pidx)->vector_width(),
|
||||
tmp, need_const);
|
||||
|
|
@ -2153,12 +2210,12 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, parms_.size() == 2);
|
||||
NetExpr*tmp;
|
||||
|
||||
tmp = elaborate_rval_expr(des, scope, IVL_VT_BOOL,
|
||||
32, parms_[0], false);
|
||||
tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
|
||||
IVL_VT_BOOL, 32, parms_[0], false);
|
||||
sys_expr->parm(1, tmp);
|
||||
|
||||
tmp = elaborate_rval_expr(des, scope, IVL_VT_BOOL,
|
||||
32, parms_[1], false);
|
||||
tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
|
||||
IVL_VT_BOOL, 32, parms_[1], false);
|
||||
sys_expr->parm(2, tmp);
|
||||
|
||||
return sys_expr;
|
||||
|
|
@ -2902,7 +2959,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (net->net_type() != ntype) {
|
||||
if (! ntype->type_compatible(net->net_type())) {
|
||||
cerr << get_fileline() << ": internal_error: "
|
||||
<< "net type doesn't match context type." << endl;
|
||||
|
||||
|
|
@ -2920,7 +2977,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
ntype->debug_dump(cerr);
|
||||
cerr << endl;
|
||||
}
|
||||
ivl_assert(*this, net->net_type() == ntype);
|
||||
ivl_assert(*this, ntype->type_compatible(net->net_type()));
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
|
|
@ -4619,7 +4676,8 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
|||
// While there are default arguments, check them.
|
||||
if (idx <= parms_.size() && parms_[idx-1]) {
|
||||
PExpr*tmp = parms_[idx-1];
|
||||
parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->data_type(),
|
||||
parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->net_type(),
|
||||
def->port(idx)->data_type(),
|
||||
def->port(idx)->vector_width(),
|
||||
tmp, false);
|
||||
if (parms[idx] == 0)
|
||||
|
|
|
|||
30
elaborate.cc
30
elaborate.cc
|
|
@ -84,7 +84,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
<< " width=" << lval->vector_width() << endl;
|
||||
}
|
||||
|
||||
NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->data_type(),
|
||||
NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->net_type(),
|
||||
lval->data_type(),
|
||||
lval->vector_width(), pin(1));
|
||||
|
||||
if (rval_expr == 0) {
|
||||
|
|
@ -2249,7 +2250,11 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
|||
{
|
||||
ivl_assert(*this, rval_);
|
||||
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval(),
|
||||
// Don't have a good value for the lv_net_type argument to
|
||||
// elaborate_rval_expr, so punt and pass nil. In the future we
|
||||
// should look into fixing calls to this method to pass a
|
||||
// net_type instead of the separate lv_width/lv_type values.
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, 0, lv_type, lv_width, rval(),
|
||||
is_constant_);
|
||||
|
||||
if (!is_constant_ || !rv) return rv;
|
||||
|
|
@ -3463,7 +3468,8 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
|||
NetExpr*rv = 0;
|
||||
|
||||
if (parms_idx<parms_.size() && parms_[parms_idx]) {
|
||||
rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_ [parms_idx]);
|
||||
rv = elaborate_rval_expr(des, scope, port->net_type(),
|
||||
lv_type, wid, parms_ [parms_idx]);
|
||||
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) {
|
||||
cerr << evt->get_fileline() << ": error: An event '"
|
||||
<< evt->event()->name() << "' can not be a user "
|
||||
|
|
@ -3617,7 +3623,11 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
|
|||
unsigned lwid = count_lval_width(lval);
|
||||
ivl_variable_type_t ltype = lval->expr_type();
|
||||
|
||||
NetExpr*rexp = elaborate_rval_expr(des, scope, ltype, lwid, expr_);
|
||||
// Need to figure out a better thing to do about the
|
||||
// lv_net_type argument to elaborate_rval_expr here. This
|
||||
// would entail getting the NetAssign_ to give us an
|
||||
// ivl_type_t as needed.
|
||||
NetExpr*rexp = elaborate_rval_expr(des, scope, 0, ltype, lwid, expr_);
|
||||
if (rexp == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -4295,7 +4305,11 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
|||
unsigned lwid = count_lval_width(lval);
|
||||
ivl_variable_type_t ltype = lval->expr_type();
|
||||
|
||||
NetExpr*rexp = elaborate_rval_expr(des, scope, ltype, lwid, expr_);
|
||||
// Like a variety of other assigns, we need to figure out a
|
||||
// better way to get a reasonable lv_net_type value, and that
|
||||
// probably will involve NetAssign_ having a method for
|
||||
// synthesizing one as needed.
|
||||
NetExpr*rexp = elaborate_rval_expr(des, scope, 0, ltype, lwid, expr_);
|
||||
if (rexp == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -4351,7 +4365,8 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* Make the r-value of the initial assignment, and size it
|
||||
properly. Then use it to build the assignment statement. */
|
||||
etmp = elaborate_rval_expr(des, scope, lv->expr_type(), lv->lwidth(),
|
||||
etmp = elaborate_rval_expr(des, scope, sig->net_type(),
|
||||
lv->expr_type(), lv->lwidth(),
|
||||
expr1_);
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
@ -4566,7 +4581,8 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
|
|||
unsigned long wid = res->vector_width();
|
||||
NetAssign_*lv = new NetAssign_(res);
|
||||
|
||||
NetExpr*val = elaborate_rval_expr(des, scope, lv_type, wid, expr_);
|
||||
NetExpr*val = elaborate_rval_expr(des, scope, res->net_type(),
|
||||
lv_type, wid, expr_);
|
||||
|
||||
NetBlock*proc = new NetBlock(NetBlock::SEQU, 0);
|
||||
proc->set_line( *this );
|
||||
|
|
|
|||
10
netdarray.cc
10
netdarray.cc
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "netdarray.h"
|
||||
# include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -34,3 +35,12 @@ ivl_variable_type_t netdarray_t::base_type(void) const
|
|||
{
|
||||
return IVL_VT_DARRAY;
|
||||
}
|
||||
|
||||
bool netdarray_t::test_compatibility(ivl_type_t that) const
|
||||
{
|
||||
const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that);
|
||||
if (that_da == 0)
|
||||
return false;
|
||||
|
||||
return element_type()->type_compatible(that_da->element_type());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class netdarray_t : public netarray_t {
|
|||
std::ostream& debug_dump(std::ostream&) const;
|
||||
|
||||
private:
|
||||
bool test_compatibility(ivl_type_t that) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
20
netmisc.cc
20
netmisc.cc
|
|
@ -809,6 +809,26 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
ivl_type_t lv_net_type, bool need_const)
|
||||
{
|
||||
if (debug_elaborate) {
|
||||
cerr << pe->get_fileline() << ": elab_and_eval: "
|
||||
<< "pe=" << *pe
|
||||
<< ", lv_net_type=" << *lv_net_type << endl;
|
||||
}
|
||||
|
||||
// Elaborate the expression using the more general
|
||||
// elaborate_expr method.
|
||||
unsigned flags = PExpr::NO_FLAGS;
|
||||
if (need_const)
|
||||
flags |= PExpr::NEED_CONST;
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, lv_net_type, flags);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
||||
unsigned arg_idx, PExpr*pe, bool need_const)
|
||||
{
|
||||
|
|
|
|||
15
netmisc.h
15
netmisc.h
|
|
@ -244,6 +244,15 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
|||
bool annotatable =false,
|
||||
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE);
|
||||
|
||||
/*
|
||||
* This form of elab_and_eval uses the ivl_type_t to carry type
|
||||
* information instead of the piecemeal form. We should transition to
|
||||
* this form as we reasonably can.
|
||||
*/
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
PExpr*expr, ivl_type_t lv_net_type,
|
||||
bool need_const);
|
||||
|
||||
/*
|
||||
* This function is a variant of elab_and_eval that elaborates and
|
||||
* evaluates the arguments of a system task.
|
||||
|
|
@ -256,8 +265,14 @@ extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope,
|
|||
* of an assignment, The lv_type and lv_width are the type and width
|
||||
* of the l-value, and the expr is the expression to elaborate. The
|
||||
* result is the NetExpr elaborated and evaluated. (See elab_expr.cc)
|
||||
*
|
||||
* I would rather that all calls to elaborate_rval_expr use the
|
||||
* lv_net_type argument to express the l-value type, but, for now,
|
||||
* that it not possible. Those cases will be indicated by the
|
||||
* lv_net_type being set to nil.
|
||||
*/
|
||||
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width, PExpr*expr,
|
||||
bool need_const =false);
|
||||
|
|
|
|||
13
nettypes.cc
13
nettypes.cc
|
|
@ -46,6 +46,19 @@ bool ivl_type_s::get_signed() const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ivl_type_s::type_compatible(ivl_type_t that) const
|
||||
{
|
||||
if (this == that)
|
||||
return true;
|
||||
|
||||
return test_compatibility(that);
|
||||
}
|
||||
|
||||
bool ivl_type_s::test_compatibility(const ivl_type_s*that) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
netarray_t::~netarray_t()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
22
nettypes.h
22
nettypes.h
|
|
@ -44,7 +44,17 @@ class ivl_type_s {
|
|||
virtual ivl_variable_type_t base_type() const;
|
||||
virtual bool get_signed() const;
|
||||
|
||||
// Return true if "that" type is compatible with this
|
||||
// type. Compatibile means the types are essentially the same.
|
||||
bool type_compatible(ivl_type_t that) const;
|
||||
|
||||
virtual std::ostream& debug_dump(std::ostream&) const;
|
||||
|
||||
private:
|
||||
// The "type_compatibile" method uses this virtual method to
|
||||
// invoke type-specific tests of compatibility. This should
|
||||
// only be called by the type_compatible method above.
|
||||
virtual bool test_compatibility(ivl_type_t that) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -100,6 +110,18 @@ class netrange_t {
|
|||
inline long get_msb() const { assert(defined()); return msb_; }
|
||||
inline long get_lsb() const { assert(defined()); return lsb_; }
|
||||
|
||||
inline bool operator == (const netrange_t&that) const
|
||||
{ if (msb_ != that.msb_) return false;
|
||||
if (lsb_ != that.lsb_) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator != (const netrange_t&that) const
|
||||
{ if (msb_ != that.msb_) return true;
|
||||
if (lsb_ != that.lsb_) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
long msb_;
|
||||
long lsb_;
|
||||
|
|
|
|||
20
netvector.cc
20
netvector.cc
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "netvector.h"
|
||||
# include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -62,3 +63,22 @@ vector<netrange_t> netvector_t::slice_dimensions() const
|
|||
{
|
||||
return packed_dims_;
|
||||
}
|
||||
|
||||
bool netvector_t::test_compatibility(ivl_type_t that) const
|
||||
{
|
||||
const netvector_t*that_st = dynamic_cast<const netvector_t*>(that);
|
||||
if (that_st == 0)
|
||||
return false;
|
||||
|
||||
if (type_ != that_st->type_)
|
||||
return false;
|
||||
if (packed_dims_.size() != that_st->packed_dims_.size())
|
||||
return false;
|
||||
|
||||
for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1) {
|
||||
if (packed_dims_[idx] != that_st->packed_dims_[idx])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ class netvector_t : public ivl_type_s {
|
|||
static netvector_t scalar_bool;
|
||||
static netvector_t scalar_logic;
|
||||
|
||||
private:
|
||||
bool test_compatibility(ivl_type_t that) const;
|
||||
|
||||
private:
|
||||
std::vector<netrange_t> packed_dims_;
|
||||
ivl_variable_type_t type_;
|
||||
|
|
|
|||
7
parse.y
7
parse.y
|
|
@ -669,15 +669,14 @@ source_text : description_list | ;
|
|||
|
||||
assignment_pattern /* IEEE1800-2005: A.6.7.1 */
|
||||
: K_LP expression_list_proper '}'
|
||||
{ PEVoid*tmp = new PEVoid;
|
||||
{ PEAssignPattern*tmp = new PEAssignPattern(*$2);
|
||||
FILE_NAME(tmp, @1);
|
||||
yyerror(@1, "sorry: Assignment patterns (array literals) not supported.");
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_LP '}'
|
||||
{ PEVoid*tmp = new PEVoid;
|
||||
{ PEAssignPattern*tmp = new PEAssignPattern;
|
||||
FILE_NAME(tmp, @1);
|
||||
yyerror(@1, "sorry: Assignment patterns (empty array literals) not supported.");
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
|
|||
|
|
@ -230,6 +230,19 @@ void PExpr::dump(ostream&out) const
|
|||
out << typeid(*this).name();
|
||||
}
|
||||
|
||||
void PEAssignPattern::dump(ostream&out) const
|
||||
{
|
||||
out << "'{";
|
||||
if (parms_.size() > 0) {
|
||||
parms_[0]->dump(out);
|
||||
for (size_t idx = 1 ; idx < parms_.size() ; idx += 1) {
|
||||
out << ", ";
|
||||
parms_[idx]->dump(out);
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
}
|
||||
|
||||
void PEConcat::dump(ostream&out) const
|
||||
{
|
||||
if (repeat_)
|
||||
|
|
|
|||
Loading…
Reference in New Issue