diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 520a3e1bc..6201a6325 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -208,11 +208,16 @@ void ExpAggregate::choice_t::dump(ostream&out, int indent) const return; } - if (expr_) { + if (expr_.get()) { expr_->dump(out, indent); return; } + if (range_.get()) { + range_->dump(out, indent); + return; + } + out << setw(indent) << "" << "?choice_t?" << endl; } @@ -375,6 +380,8 @@ void ExpName::dump(ostream&out, int indent) const { out << setw(indent) << "" << "ExpName(\"" << name_ << "\")" << " at " << get_fileline() << endl; + if (prefix_.get()) + prefix_->dump(out, indent+8); if (index_) index_->dump(out, indent+6); if (lsb_) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 1334df43e..a6aee6e47 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -137,25 +137,26 @@ ExpAggregate::choice_t::choice_t(Expression*exp) } ExpAggregate::choice_t::choice_t() -: expr_(0) +{ +} + +ExpAggregate::choice_t::choice_t(prange_t*rang) +: range_(rang) { } ExpAggregate::choice_t::~choice_t() { - if (expr_) delete expr_; } bool ExpAggregate::choice_t::others() const { - return expr_ == 0; + return expr_.get() == 0 && range_.get() == 0; } Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag) { - Expression*res = expr_; - if (detach_flag) - expr_ = 0; + Expression*res = detach_flag? expr_.release() : expr_.get(); return res; } @@ -371,6 +372,16 @@ ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb) { } +ExpName::ExpName(ExpName*prefix, perm_string nn) +: prefix_(prefix), name_(nn), index_(0), lsb_(0) +{ +} + +ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb) +: prefix_(prefix), name_(nn), index_(msb), lsb_(lsb) +{ +} + ExpName::~ExpName() { delete index_; diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index f4b7ced26..0f44da44d 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -24,8 +24,10 @@ # include "entity.h" # include # include +# include # include +class prange_t; class Entity; class Architecture; class ScopeBase; @@ -185,6 +187,8 @@ class ExpAggregate : public Expression { explicit choice_t(Expression*exp); // Create a named choice explicit choice_t(perm_string name); + // discreate_range choice + explicit choice_t(prange_t*ran); ~choice_t(); // true if this represents an "others" choice @@ -195,7 +199,8 @@ class ExpAggregate : public Expression { void dump(ostream&out, int indent) const; private: - Expression*expr_; + std::auto_ptrexpr_; + std::auto_ptr range_; private: // not implemented choice_t(const choice_t&); choice_t& operator= (const choice_t&); @@ -461,6 +466,8 @@ class ExpName : public Expression { explicit ExpName(perm_string nn); ExpName(perm_string nn, std::list*indices); ExpName(perm_string nn, Expression*msb, Expression*lsb); + ExpName(ExpName*prefix, perm_string nn); + ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb); ~ExpName(); public: // Base methods @@ -478,6 +485,7 @@ class ExpName : public Expression { const char* name() const; private: + std::auto_ptr prefix_; perm_string name_; Expression*index_; Expression*lsb_; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 679f2fbb7..6d5dc797f 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -43,6 +43,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) { int errors = 0; + if (prefix_.get()) { + cerr << get_fileline() << ": sorry: I don't know how to elaborate " + << "ExpName prefix of " << name_ + << " in l-value expressions." << endl; + errors += 1; + } + const VType*found_type = 0; if (const InterfacePort*cur = ent->find_port(name_)) { @@ -116,6 +123,12 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv { int errors = 0; + if (prefix_.get()) { + cerr << get_fileline() << ": sorry: I don't know how to elaborate " + << "ExpName prefix parts in r-value expressions." << endl; + errors += 1; + } + if (const InterfacePort*cur = ent->find_port(name_)) { /* IEEE 1076-2008, p.80: * For a formal port IN, associated port should be IN, OUT, INOUT or BUFFER @@ -398,6 +411,12 @@ int ExpLogical::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) const VType* ExpName::probe_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; + return 0; + } + if (const InterfacePort*cur = ent->find_port(name_)) { ivl_assert(*this, cur->type); return cur->type; diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index c5141c4f6..30b66dbfc 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -515,6 +515,11 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; + if (prefix_.get()) { + cerr << get_fileline() << ": sorry: I don't know how to emit ExpName prefix parts." << endl; + errors += 1; + } + out << "\\" << name_ << " "; if (index_) { out << "["; diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 3596e9fd5..62c3929b7 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -76,6 +76,11 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const const VType*type; Expression*exp; + if (prefix_.get()) { + cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl; + return false; + } + bool rc = scope->find_constant(name_, type, exp); if (rc == false) return false; @@ -85,6 +90,11 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const { + if (prefix_.get()) { + cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl; + return false; + } + const InterfacePort*gen = ent->find_generic(name_); if (gen) { cerr << get_fileline() << ": sorry: I don't necessarily handle generic overrides." << endl; diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 2427f7fba..16b47fae0 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -108,6 +108,11 @@ void ExpLogical::write_to_stream(ostream&) void ExpName::write_to_stream(ostream&fd) { + if (prefix_.get()) { + prefix_->write_to_stream(fd); + fd << "."; + } + fd << name_; if (index_) { fd << "("; diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index f2d26ffdf..b7d69ede0 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -167,6 +167,37 @@ static Expression*aggregate_or_primary(const YYLTYPE&loc, std::listextract_expression(); } +static ExpName*make_name_from_prefix(const YYLTYPE&loc, const vector*names) +{ + ExpName*cur = new ExpName(names->at(0)); + FILE_NAME(cur, loc); + + for (size_t idx = 1 ; idx < names->size() ; idx += 1) { + ExpName*tmp = new ExpName(cur, names->at(idx)); + FILE_NAME(tmp, loc); + cur = tmp; + } + + return cur; +} + +static ExpName*make_name_from_prefix(const YYLTYPE&loc, const vector*names, Expression*msb, Expression*lsb) +{ + ExpName*cur = new ExpName(names->at(0)); + FILE_NAME(cur, loc); + + for (size_t idx = 1 ; idx < (names->size()-1) ; idx += 1) { + ExpName*tmp = new ExpName(cur, names->at(idx)); + FILE_NAME(tmp, loc); + cur = tmp; + } + + ExpName*result = new ExpName(cur, names->back(), msb, lsb); + FILE_NAME(result, loc); + + return result; +} + static list* record_elements(list*names, const VType*type) { @@ -561,6 +592,8 @@ choice { $$ = new ExpAggregate::choice_t($1);} | K_others { $$ = new ExpAggregate::choice_t; } + | range /* discrete_range: range */ + { $$ = new ExpAggregate::choice_t($1); } ; choices @@ -678,6 +711,22 @@ concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */ SignalAssignment*tmpa = new SignalAssignment(name, tmp); FILE_NAME(tmpa, @1); + $$ = tmpa; + } + + /* Error recovery rules. */ + + | name LEQ error K_when expression else_when_waveforms ';' + { errormsg(@3, "Syntax error in waveform of conditional signal assignment.\n"); + ExpConditional*tmp = new ExpConditional($5, 0, $6); + FILE_NAME(tmp, @3); + delete $6; + + ExpName*name = dynamic_cast ($1); + assert(name); + SignalAssignment*tmpa = new SignalAssignment(name, tmp); + FILE_NAME(tmpa, @1); + $$ = tmpa; } ; @@ -1445,6 +1494,13 @@ name delete[]$1; $$ = tmp; } + + | selected_name + { ExpName*tmp = make_name_from_prefix(@1, $1); + delete $1; + $$ = tmp; + } + /* Note that this rule can match array element selects and various function calls. The only way we can tell the difference is from left context, namely whether the name is a type name or function @@ -1467,6 +1523,11 @@ name delete[]$1; $$ = tmp; } + | selected_name '(' range ')' + { ExpName*tmp = make_name_from_prefix(@1, $1, $3->msb(), $3->lsb()); + delete $1; + $$ = tmp; + } ; /* Handle name lists as lists of expressions. */ @@ -1857,12 +1918,10 @@ secondary_unit selected_name : prefix '.' suffix - { - std::vector* tmp = $1; - tmp->push_back(lex_strings.make($3)); - delete[] $3; - - $$ = tmp; + { std::vector* tmp = $1; + tmp->push_back(lex_strings.make($3)); + delete[] $3; + $$ = tmp; } ;