Type name expressions down to elaboration.

This commit is contained in:
Stephen Williams 2013-12-16 03:49:57 +02:00
parent a3b29dd70b
commit 8a4d769b3d
5 changed files with 82 additions and 9 deletions

View File

@ -540,6 +540,15 @@ bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|| fal_->has_aa_term(des, scope);
}
PETypename::PETypename(data_type_t*dt)
: data_type_(dt)
{
}
PETypename::~PETypename()
{
}
PEUnary::PEUnary(char op, PExpr*ex)
: op_(op), expr_(ex)
{

15
PExpr.h
View File

@ -660,6 +660,21 @@ class PEString : public PExpr {
char*text_;
};
class PETypename : public PExpr {
public:
explicit PETypename(data_type_t*data_type);
~PETypename();
virtual void dump(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;
private:
data_type_t*data_type_;
};
class PEUnary : public PExpr {
public:

View File

@ -188,7 +188,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
* 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)
unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&)
{
expr_type_ = IVL_VT_DARRAY;
expr_width_ = 1;
@ -1078,10 +1078,14 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
if (expr == 0)
return 0;
// The argument type/width is self-determined and doesn't
// affect the result type/width.
width_mode_t arg_mode = SIZED;
expr->test_width(des, scope, arg_mode);
if (! dynamic_cast<PETypename*>(expr)) {
// The argument type/width is self-determined and doesn't
// affect the result type/width. Note that if the
// argument is a type name (a special case) then
// don't bother with this step.
width_mode_t arg_mode = SIZED;
expr->test_width(des, scope, arg_mode);
}
expr_type_ = IVL_VT_BOOL;
expr_width_ = integer_width;
@ -1393,11 +1397,18 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
PExpr*expr = parms_[0];
verinum val ( (uint64_t)expr->expr_width(), integer_width);
NetEConst*sub = new NetEConst(val);
sub->set_line(*this);
if (PETypename*type_expr = dynamic_cast<PETypename*>(expr)) {
cerr << get_fileline() << ": sorry: "
<< "I don't yet support typename argumets to $bits." << endl;
des->errors += 1;
return 0;
} else {
verinum val ( (uint64_t)expr->expr_width(), integer_width);
NetEConst*sub = new NetEConst(val);
sub->set_line(*this);
return cast_to_width_(sub, expr_wid);
return cast_to_width_(sub, expr_wid);
}
}
/* Interpret the internal $is_signed system function to return
@ -5158,6 +5169,31 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
return tmp;
}
/*
* A typename expression is only legal in very narrow cases. This is
* just a placeholder.
*/
unsigned PETypename::test_width(Design*des, NetScope*, width_mode_t&)
{
cerr << get_fileline() << ": error: "
<< "Type names are not valid expressions here." << endl;
des->errors += 1;
expr_type_ = IVL_VT_NO_TYPE;
expr_width_ = 1;
min_width_ = 1;
signed_flag_ = false;
return expr_width_;
}
NetExpr*PETypename::elaborate_expr(Design*des, NetScope*,
ivl_type_t, unsigned) const
{
cerr << get_fileline() << ": error: Type name not a valid expression here." << endl;
des->errors += 1;
return 0;
}
unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
{
switch (op_) {

View File

@ -3097,6 +3097,14 @@ expr_primary
delete[]$1;
}
/* There are a few special cases (notably $bits argument) where the
expression may be a type name. Let the elaborator sort this out. */
| TYPE_IDENTIFIER
{ PETypename*tmp = new PETypename($1);
FILE_NAME(tmp,@1);
$$ = tmp;
}
/* The hierarchy_identifier rule matches simple identifiers as well as
indexed arrays and part selects */

View File

@ -385,6 +385,11 @@ void PETernary::dump(ostream&out) const
out << "(" << *expr_ << ")?(" << *tru_ << "):(" << *fal_ << ")";
}
void PETypename::dump(ostream&fd) const
{
fd << "<type>";
}
void PEUnary::dump(ostream&out) const
{
switch (op_) {