diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 2cf89b78c..df1b9bf81 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -283,7 +283,9 @@ class ExpAggregate : public Expression { private: int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype); + int elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype); int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype); + int emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype); private: // This is the elements as directly parsed. @@ -575,6 +577,7 @@ class ExpName : public Expression { bool symbolic_compare(const Expression*that) const; void dump(ostream&out, int indent = 0) const; const char* name() const; + inline perm_string peek_name() const { return name_; } void set_range(Expression*msb, Expression*lsb); diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index a53b7d23c..ce8dd6ab9 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -411,6 +411,9 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype if (const VTypeArray*larray = dynamic_cast(ltype)) { return elaborate_expr_array_(ent, arc, larray); } + else if(const VTypeRecord*lrecord = dynamic_cast(ltype)) { + return elaborate_expr_record_(ent, arc, lrecord); + } cerr << get_fileline() << ": internal error: I don't know how to elaborate aggregate expressions. type=" << typeid(*ltype).name() << endl; return 1; @@ -476,6 +479,48 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp return errors; } +int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype) +{ + int errors = 0; + + aggregate_.resize(elements_.size()); + + // Translate the elements_ array to the aggregate_ array. In + // the target array, each expression is attached to a single + // choice. + for (size_t edx = 0 ; edx < elements_.size() ; edx += 1) { + element_t*ecur = elements_[edx]; + + // it is invalid to have more than one choice in record assignment + ivl_assert(*this, ecur->count_choices() == 1); + + ecur->map_choices(&aggregate_[edx]); + } + + // Now run through the more convenient mapping and elaborate + // all the expressions that I find. + for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) { + ivl_assert(*this, !aggregate_[idx].alias_flag); + + choice_t*ch = aggregate_[idx].choice; + ivl_assert(*this, !ch->others()); + + // Get the appropriate type for a field + const ExpName*field = dynamic_cast(ch->simple_expression(false)); + ivl_assert(*this, field); + + perm_string field_name = field->peek_name(); + const VTypeRecord::element_t*el = ltype->element_by_name(field_name); + + errors += aggregate_[idx].expr->elaborate_expr(ent, arc, el->peek_type()); + } + + // done with the obsolete elements_ vector. + elements_.clear(); + + return errors; +} + void ExpAggregate::element_t::map_choices(ExpAggregate::choice_element*dst) { for (size_t idx = 0 ; idx < fields_.size() ; idx += 1) { diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 63bde19e1..32778d8ea 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -95,6 +95,8 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc) if (const VTypeArray*atype = dynamic_cast (use_type)) return emit_array_(out, ent, arc, atype); + else if (const VTypeRecord*arecord = dynamic_cast (use_type)) + return emit_record_(out, ent, arc, arecord); out << "/* " << get_fileline() << ": internal error: " << "I don't know how to elab/emit aggregate in " << typeid(use_type).name() @@ -271,6 +273,30 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V return errors; } +int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype) +{ + int errors = 0; + + out << "{"; + + for (size_t idx = 0 ; idx < aggregate_.size() ; idx += 1) { + ivl_assert(*this, !aggregate_[idx].choice->others()); + ivl_assert(*this, !aggregate_[idx].choice->range_expressions()); + + Expression*val = aggregate_[idx].expr; + ivl_assert(*this, val); + + if(idx != 0) + out << ","; + + errors += val->emit(out, ent, arc); + } + + out << "}"; + + return errors; +} + int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0;