diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 0f44da44d..739f8079d 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -484,6 +484,10 @@ class ExpName : public Expression { void dump(ostream&out, int indent = 0) const; const char* name() const; + private: + const VType* probe_prefix_type_(Entity*ent, Architecture*arc) const; + const VType* probe_prefixed_type_(Entity*ent, Architecture*arc) const; + private: std::auto_ptr prefix_; perm_string name_; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 6d5dc797f..1386a549d 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -409,14 +409,54 @@ int ExpLogical::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) return errors; } -const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const +const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const { if (prefix_.get()) { - cerr << get_fileline() << ": sorry: I don't know how to probe type " - << "of " << name_ << " with prefix parts." << endl; + cerr << get_fileline() << ": sorry: I do not know how to support nested prefix parts." << endl; return 0; } + const VType*type = probe_type(ent, arc); + return type; +} + +/* + * This method is the probe_type() imlementation for ExpName objects + * that have prefix parts. In this case we try to get the type of the + * prefix and interpret the name in that context. + */ +const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const +{ + // First, get the type of the prefix. + const VType*prefix_type = prefix_->probe_prefix_type_(ent, arc); + if (prefix_type == 0) { + return 0; + } + + // If the prefix type is a record, then the current name is + // the name of a member. + if (const VTypeRecord*pref_record = dynamic_cast (prefix_type)) { + const VTypeRecord::element_t*element = pref_record->element_by_name(name_); + ivl_assert(*this, element); + + const VType*element_type = element->peek_type(); + ivl_assert(*this, element_type); + + return element_type; + } + + cerr << get_fileline() << ": sorry: I don't know how to probe " + << "prefix type " << typeid(*prefix_type).name() + << " of " << name_ << "." << endl; + + return 0; +} + +const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const +{ + if (prefix_.get()) + return probe_prefixed_type_(ent, arc); + if (const InterfacePort*cur = ent->find_port(name_)) { ivl_assert(*this, cur->type); return cur->type; diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 5c346ea5f..cd39a4fe9 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -183,6 +183,18 @@ void VTypeRecord::show(ostream&out) const write_to_stream(out); } +const VTypeRecord::element_t* VTypeRecord::element_by_name(perm_string name) const +{ + for (vector::const_iterator cur = elements_.begin() + ; cur != elements_.end() ; ++cur) { + element_t*curp = *cur; + if (curp->peek_name() == name) + return curp; + } + + return 0; +} + VTypeRecord::element_t::element_t(perm_string name, const VType*typ) : name_(name), type_(typ) { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 5d86f05c9..ac15a68b3 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -209,6 +209,9 @@ class VTypeRecord : public VType { void write_to_stream(std::ostream&) const; + inline perm_string peek_name() const { return name_; } + inline const VType* peek_type() const { return type_; } + private: perm_string name_; const VType*type_; @@ -226,6 +229,9 @@ class VTypeRecord : public VType { void show(std::ostream&) const; int emit_def(std::ostream&out, perm_string name) const; + + const element_t* element_by_name(perm_string name) const; + private: int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const;