Include a calculation of the expression type in test_width methods.

The type of the sub-expression is sometimes needed by clients of the
test_width methods, so add that as an output.
This commit is contained in:
Stephen Williams 2008-09-26 22:20:11 -07:00
parent 42d412c626
commit 3296b1dee3
3 changed files with 126 additions and 28 deletions

18
PExpr.h
View File

@ -63,12 +63,16 @@ class PExpr : public LineInfo {
// the subexpression should not make l-value related // the subexpression should not make l-value related
// optimizations. // optimizations.
// //
// The expr_type is an output argument that gives the
// calculated type for the expression.
//
// The unsigned_flag is set to true if the expression is // The unsigned_flag is set to true if the expression is
// unsized and therefore expandable. This happens if a // unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make // sub-expression is an unsized literal. Some expressions make
// special use of that. // special use of that.
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
// During the elaborate_sig phase, we may need to scan // During the elaborate_sig phase, we may need to scan
@ -213,6 +217,7 @@ class PEFNumber : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*, virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const; int expr_width, bool sys_task_arg) const;
@ -238,6 +243,7 @@ class PEIdent : public PExpr {
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -353,6 +359,7 @@ class PENumber : public PExpr {
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*, virtual NetEConst*elaborate_expr(Design*des, NetScope*,
@ -389,6 +396,7 @@ class PEString : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*, virtual NetEConst*elaborate_expr(Design*des, NetScope*,
@ -412,6 +420,7 @@ class PEUnary : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -440,6 +449,7 @@ class PEBinary : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -479,6 +489,7 @@ class PEBComp : public PEBinary {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag) const; bool&flag) const;
NetExpr* elaborate_expr(Design*des, NetScope*scope, NetExpr* elaborate_expr(Design*des, NetScope*scope,
@ -492,7 +503,9 @@ class PEBShift : public PEBinary {
~PEBShift(); ~PEBShift();
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&flag) const; unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*, virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const; int expr_width, bool sys_task_arg) const;
}; };
@ -512,6 +525,7 @@ class PETernary : public PExpr {
virtual void dump(ostream&out) const; virtual void dump(ostream&out) const;
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const; virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -555,6 +569,7 @@ class PECallFunction : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
private: private:
@ -567,6 +582,7 @@ class PECallFunction : public PExpr {
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, int expr_wid) const; NetExpr* elaborate_access_func_(Design*des, NetScope*scope, int expr_wid) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope, unsigned test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const; bool&unsized_flag) const;
}; };

View File

@ -48,6 +48,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
{ {
int expr_wid = 0; int expr_wid = 0;
bool unsized_flag = false; bool unsized_flag = false;
ivl_variable_type_t rval_type = IVL_VT_NO_TYPE;
switch (data_type_lv) { switch (data_type_lv) {
case IVL_VT_REAL: case IVL_VT_REAL:
@ -61,7 +62,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
guess it will be the l-value width, but it may turn guess it will be the l-value width, but it may turn
out to be something else based on self-determined out to be something else based on self-determined
widths inside. */ widths inside. */
expr_wid = expr->test_width(des, scope, expr_wid_lv, expr_wid_lv, unsized_flag); expr_wid = expr->test_width(des, scope, expr_wid_lv, expr_wid_lv, rval_type, unsized_flag);
if (debug_elaborate) { if (debug_elaborate) {
cerr << expr->get_fileline() << ": debug: r-value tested " cerr << expr->get_fileline() << ": debug: r-value tested "
@ -88,7 +89,8 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
* minimum width that is passed in. * minimum width that is passed in.
*/ */
unsigned PExpr::test_width(Design*des, NetScope*scope, unsigned PExpr::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&) const unsigned min, unsigned lval,
ivl_variable_type_t&, bool&) const
{ {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: test_width defaults to " cerr << get_fileline() << ": debug: test_width defaults to "
@ -109,20 +111,32 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, int, bool) const
} }
unsigned PEBinary::test_width(Design*des, NetScope*scope, unsigned PEBinary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&unsized_flag) const unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const
{ {
bool flag_left = false; bool flag_left = false;
bool flag_right = false; bool flag_right = false;
unsigned wid_left = left_->test_width(des,scope, min, 0, flag_left); ivl_variable_type_t expr_type_left = IVL_VT_NO_TYPE;
unsigned wid_right = right_->test_width(des,scope, min, 0, flag_right); ivl_variable_type_t expr_type_right= IVL_VT_NO_TYPE;
unsigned wid_left = left_->test_width(des,scope, min, 0, expr_type_left, flag_left);
unsigned wid_right = right_->test_width(des,scope, min, 0, expr_type_right, flag_right);
if (flag_left || flag_right) if (flag_left || flag_right)
unsized_flag = true; unsized_flag = true;
if (expr_type_left == IVL_VT_REAL || expr_type_right == IVL_VT_REAL)
expr_type = IVL_VT_REAL;
else if (expr_type_left==IVL_VT_LOGIC || expr_type_right==IVL_VT_LOGIC)
expr_type = IVL_VT_LOGIC;
else
expr_type = IVL_VT_BOOL;
switch (op_) { switch (op_) {
case '+': case '+':
case '-': case '-':
if (unsized_flag) { if (unsized_flag && type_is_vectorable(expr_type)) {
wid_left += 1; wid_left += 1;
wid_right += 1; wid_right += 1;
} }
@ -618,8 +632,11 @@ NetExpr* PEBinary::elaborate_expr_base_add_(Design*des,
return tmp; return tmp;
} }
unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned, bool&) const unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned,
ivl_variable_type_t&expr_type,
bool&) const
{ {
expr_type = IVL_VT_LOGIC;
return 1; return 1;
} }
@ -630,12 +647,14 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
assert(right_); assert(right_);
bool unsized_flag = false; bool unsized_flag = false;
unsigned left_width = left_->test_width(des, scope, 0, 0, unsized_flag); ivl_variable_type_t left_type = IVL_VT_NO_TYPE;
unsigned left_width = left_->test_width(des, scope, 0, 0, left_type, unsized_flag);
bool save_flag = unsized_flag; bool save_flag = unsized_flag;
unsigned right_width = right_->test_width(des, scope, 0, 0, unsized_flag); ivl_variable_type_t right_type = IVL_VT_NO_TYPE;
unsigned right_width = right_->test_width(des, scope, 0, 0, right_type, unsized_flag);
if (save_flag != unsized_flag) if (save_flag != unsized_flag)
left_width = left_->test_width(des, scope, 0, 0, unsized_flag); left_width = left_->test_width(des, scope, 0, 0, left_type, unsized_flag);
/* Width of operands is self-determined. */ /* Width of operands is self-determined. */
int use_wid = left_width; int use_wid = left_width;
@ -664,9 +683,11 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
} }
unsigned PEBShift::test_width(Design*des, NetScope*scope, unsigned PEBShift::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&unsized_flag) const unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const
{ {
unsigned wid_left = left_->test_width(des,scope,min, 0, unsized_flag); unsigned wid_left = left_->test_width(des,scope,min, 0, expr_type, unsized_flag);
// The right expression is self-determined and has no impact // The right expression is self-determined and has no impact
// on the expression size that is generated. // on the expression size that is generated.
@ -709,6 +730,7 @@ NetExpr*PEBShift::elaborate_expr(Design*des, NetScope*scope,
unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope, unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag) const
{ {
perm_string name = peek_tail_name(path_); perm_string name = peek_tail_name(path_);
@ -717,7 +739,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
PExpr*expr = parms_[0]; PExpr*expr = parms_[0];
if (expr == 0) if (expr == 0)
return 0; return 0;
unsigned wid = expr->test_width(des, scope, min, lval, unsized_flag); unsigned wid = expr->test_width(des, scope, min, lval, expr_type, unsized_flag);
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width" cerr << get_fileline() << ": debug: test_width"
<< " of $signed/$unsigned returns test_width" << " of $signed/$unsigned returns test_width"
@ -725,19 +747,50 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
return wid; return wid;
} }
if (name=="$sizeof" || name=="$bits") {
if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width"
<< " of $sizeof/$bits returns test_width"
<< " of compiler integer." << endl;
expr_type = IVL_VT_BOOL;
return integer_width;
}
if (name=="$is_signed") {
if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width"
<< " of $is_signed returns test_width"
<< " of 1." << endl;
expr_type = IVL_VT_BOOL;
return 1;
}
/* Get the return type of the system function by looking it up
in the sfunc_table. */
const struct sfunc_return_type*sfunc_info
= lookup_sys_func(peek_tail_name(path_));
ivl_variable_type_t sfunc_type = sfunc_info->type;
unsigned wid = sfunc_info->wid;
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width " cerr << get_fileline() << ": debug: test_width "
<< "of system function " << name << "of system function " << name
<< " returns 32 always?" << endl; << " returns wid=" << wid
return 32; << ", type=" << sfunc_type << "." << endl;
return wid;
} }
unsigned PECallFunction::test_width(Design*des, NetScope*scope, unsigned PECallFunction::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag) const
{ {
if (peek_tail_name(path_)[0] == '$') if (peek_tail_name(path_)[0] == '$')
return test_width_sfunc_(des, scope, min, lval, unsized_flag); return test_width_sfunc_(des, scope, min, lval, expr_type, unsized_flag);
// The width of user defined functions depends only on the // The width of user defined functions depends only on the
// width of the return value. The arguments are entirely // width of the return value. The arguments are entirely
@ -755,12 +808,14 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope,
assert(dscope); assert(dscope);
if (NetNet*res = dscope->find_signal(dscope->basename())) { if (NetNet*res = dscope->find_signal(dscope->basename())) {
expr_type = res->data_type();
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width " cerr << get_fileline() << ": debug: test_width "
<< "of function returns width " << res->vector_width() << "of function returns width " << res->vector_width()
<< ", type=" << expr_type
<< "." << endl; << "." << endl;
if (! type_is_vectorable(res->data_type())) if (! type_is_vectorable(expr_type))
unsized_flag = true; unsized_flag = true;
return res->vector_width(); return res->vector_width();
@ -1193,8 +1248,10 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
*/ */
unsigned PEFNumber::test_width(Design*des, NetScope*scope, unsigned PEFNumber::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag) const
{ {
expr_type = IVL_VT_REAL;
unsized_flag = true; unsized_flag = true;
return 1; return 1;
} }
@ -1337,6 +1394,7 @@ bool PEIdent::calculate_param_range_(Design*des, NetScope*scope,
unsigned PEIdent::test_width(Design*des, NetScope*scope, unsigned PEIdent::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag) const
{ {
NetNet* net = 0; NetNet* net = 0;
@ -1384,13 +1442,16 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
return use_width; return use_width;
// The width of a signal expression is the width of the signal. // The width of a signal expression is the width of the signal.
if (net != 0) if (net != 0) {
expr_type = net->data_type();
return net->vector_width(); return net->vector_width();
}
// The width of a parameter name is the width of the range for // The width of a parameter name is the width of the range for
// the parameter name, if a range is declared. Otherwise, the // the parameter name, if a range is declared. Otherwise, the
// width is undefined. // width is undefined.
if (par != 0) { if (par != 0) {
expr_type = par->expr_type();
if (ex1) { if (ex1) {
ivl_assert(*this, ex2); ivl_assert(*this, ex2);
const NetEConst*ex1_const = dynamic_cast<const NetEConst*> (ex1); const NetEConst*ex1_const = dynamic_cast<const NetEConst*> (ex1);
@ -2266,8 +2327,11 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
} }
unsigned PENumber::test_width(Design*, NetScope*, unsigned PENumber::test_width(Design*, NetScope*,
unsigned min, unsigned lval, bool&unsized_flag) const unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const
{ {
expr_type = IVL_VT_LOGIC;
unsigned use_wid = value_->len(); unsigned use_wid = value_->len();
if (min > use_wid) if (min > use_wid)
use_wid = min; use_wid = min;
@ -2307,8 +2371,10 @@ NetEConst* PENumber::elaborate_expr(Design*des, NetScope*,
unsigned PEString::test_width(Design*des, NetScope*scope, unsigned PEString::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag) const
{ {
expr_type = IVL_VT_BOOL;
unsigned use_wid = text_? 8*strlen(text_) : 0; unsigned use_wid = text_? 8*strlen(text_) : 0;
if (min > use_wid) if (min > use_wid)
use_wid = min; use_wid = min;
@ -2326,11 +2392,15 @@ NetEConst* PEString::elaborate_expr(Design*des, NetScope*,
unsigned PETernary::test_width(Design*des, NetScope*scope, unsigned PETernary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag) const bool&flag) const
{ {
unsigned tru_wid = tru_->test_width(des, scope, min, lval, flag); ivl_variable_type_t tru_type = IVL_VT_NO_TYPE;
unsigned tru_wid = tru_->test_width(des, scope, min, lval, tru_type,flag);
bool initial_flag = flag; bool initial_flag = flag;
unsigned fal_wid = fal_->test_width(des, scope, min, lval, flag); ivl_variable_type_t fal_type = IVL_VT_NO_TYPE;
unsigned fal_wid = fal_->test_width(des, scope, min, lval, fal_type,flag);
// If the false clause is unsized, then try again with the // If the false clause is unsized, then try again with the
// true clause, because it might choose a different width if // true clause, because it might choose a different width if
@ -2340,9 +2410,16 @@ unsigned PETernary::test_width(Design*des, NetScope*scope,
cerr << get_fileline() << ": debug: " cerr << get_fileline() << ": debug: "
<< "False clause is unsized, so retest width of true clause." << "False clause is unsized, so retest width of true clause."
<< endl; << endl;
tru_wid = tru_->test_width(des, scope, max(min,fal_wid), lval, flag); tru_wid = tru_->test_width(des, scope, max(min,fal_wid), lval, tru_type, flag);
} }
if (tru_type == IVL_VT_REAL || fal_type == IVL_VT_REAL)
expr_type = IVL_VT_REAL;
else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC)
expr_type = IVL_VT_LOGIC;
else
expr_type = tru_type;
return max(tru_wid,fal_wid); return max(tru_wid,fal_wid);
} }
@ -2381,10 +2458,12 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
if (expr_wid < 0) { if (expr_wid < 0) {
bool flag = expr_wid == -2; bool flag = expr_wid == -2;
use_wid = this->test_width(des, scope, 0, 0, flag); ivl_variable_type_t expr_type = IVL_VT_NO_TYPE;
use_wid = this->test_width(des, scope, 0, 0, expr_type, flag);
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: " cerr << get_fileline() << ": debug: "
<< "Self-sized ternary chooses wid="<< use_wid << "Self-sized ternary chooses wid="<< use_wid
<< ", type=" << expr_type
<< endl; << endl;
ivl_assert(*this, use_wid > 0); ivl_assert(*this, use_wid > 0);
} }
@ -2466,6 +2545,7 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
unsigned PEUnary::test_width(Design*des, NetScope*scope, unsigned PEUnary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const bool&unsized_flag) const
{ {
switch (op_) { switch (op_) {
@ -2476,10 +2556,11 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope,
case 'A': // Reduction NAND (~&) case 'A': // Reduction NAND (~&)
case 'N': // Reduction NOR (~|) case 'N': // Reduction NOR (~|)
case 'X': // Reduction NXOR (~^) case 'X': // Reduction NXOR (~^)
expr_type = IVL_VT_LOGIC;
return 1; return 1;
} }
unsigned test_wid = expr_->test_width(des, scope, min, lval, unsized_flag); unsigned test_wid = expr_->test_width(des, scope, min, lval, expr_type, unsized_flag);
switch (op_) { switch (op_) {
// For these operators, the act of padding to the // For these operators, the act of padding to the
// minimum width can have an important impact on the // minimum width can have an important impact on the

View File

@ -3109,7 +3109,8 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
any other assignment statement. */ any other assignment statement. */
unsigned use_width = lv->lwidth(); unsigned use_width = lv->lwidth();
bool unsized_flag = false; bool unsized_flag = false;
use_width = expr1_->test_width(des, scope, use_width, use_width, unsized_flag); ivl_variable_type_t expr1_type = IVL_VT_NO_TYPE;
use_width = expr1_->test_width(des, scope, use_width, use_width, expr1_type, unsized_flag);
/* Make the r-value of the initial assignment, and size it /* Make the r-value of the initial assignment, and size it
properly. Then use it to build the assignment statement. */ properly. Then use it to build the assignment statement. */