diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 89714035c..d13acae1e 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -219,6 +219,13 @@ void ExpBitstring::dump(ostream&out, int indent) const out << "\"" << endl; } +void ExpCast::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "Cast to " << *res_type_ + << " at " << get_fileline() << endl; + arg_->dump(out, indent+4); +} + void ExpCharacter::dump(ostream&out, int indent) const { out << setw(indent) << "" << "Character '" << value_ << "'" @@ -302,6 +309,8 @@ void ExpName::dump(ostream&out, int indent) const << " at " << get_fileline() << endl; if (index_) index_->dump(out, indent+6); + if (lsb_) + lsb_->dump(out, indent+6); } void ExpNameALL::dump(ostream&out, int indent) const diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 8f5e0ff69..c4567e106 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -184,6 +184,15 @@ ExpBitstring::~ExpBitstring() { } +ExpCast::ExpCast(const VType*typ, Expression*arg) +: res_type_(typ), arg_(arg) +{ +} + +ExpCast::~ExpCast() +{ +} + ExpCharacter::ExpCharacter(char val) : value_(val) { @@ -249,12 +258,17 @@ ExpLogical::~ExpLogical() } ExpName::ExpName(perm_string nn) -: name_(nn), index_(0) +: name_(nn), index_(0), lsb_(0) { } ExpName::ExpName(perm_string nn, Expression*ix) -: name_(nn), index_(ix) +: name_(nn), index_(ix), lsb_(0) +{ +} + +ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb) +: name_(nn), index_(msb), lsb_(lsb) { } diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 5ea908d03..a5385371e 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -209,6 +209,24 @@ class ExpBitstring : public Expression { std::vectorvalue_; }; +class ExpCast : public Expression { + + public: + ExpCast(const VType*typ, Expression*arg); + ~ExpCast(); + + const VType*probe_type(Entity*ent, Architecture*arc) const; + int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); + int emit(ostream&out, Entity*ent, Architecture*arc); + void dump(ostream&out, int indent = 0) const; + + private: + // This is the target, result type to cast to. + const VType*res_type_; + // This is the expression being cast. + Expression*arg_; +}; + class ExpCharacter : public Expression { public: @@ -320,6 +338,7 @@ class ExpName : public Expression { public: explicit ExpName(perm_string nn); ExpName(perm_string nn, Expression*index); + ExpName(perm_string nn, Expression*msb, Expression*lsb); ~ExpName(); public: // Base methods @@ -337,6 +356,7 @@ class ExpName : public Expression { private: perm_string name_; Expression*index_; + Expression*lsb_; }; class ExpNameALL : public ExpName { diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 828bbfc7f..30cd63f97 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -180,6 +180,19 @@ int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*) return errors; } +const VType* ExpCast::probe_type(Entity*, Architecture*) const +{ + return res_type_; +} + +int ExpCast::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +{ + int errors = 0; + const VType*sub_type = arg_->probe_type(ent, arc); + errors += arg_->elaborate_expr(ent, arc, sub_type); + return errors; +} + int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype) { assert(ltype != 0); @@ -254,6 +267,9 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const if (Signal*sig = arc->find_signal(name_)) return sig->peek_type(); + if (Variable*var = arc->find_variable(name_)) + return var->peek_type(); + const VType*ctype = 0; Expression*cval = 0; if (arc->find_constant(name_, ctype, cval)) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index e0662b2db..ffc6a4461 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -145,6 +145,17 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*) return errors; } +int ExpCast::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + cerr << get_fileline() << ": sorry: I do not know how to emit cast expressions yet." << endl; + errors += 1; + + out << "/* Cast to type=" << *res_type_ << " */ "; + errors += arg_->emit(out, ent, arc); + return errors; +} + int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*, const VTypePrimitive*etype) { @@ -298,6 +309,11 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc) if (index_) { out << "["; errors += index_->emit(out, ent, arc); + + if (lsb_) { + out << ":"; + errors += lsb_->emit(out, ent, arc); + } out << "]"; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index faf8a8fce..826b952c0 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -471,6 +471,11 @@ choice { $$ = 0; } ; +choices + : choices '|' choice + | choice + ; + component_configuration : K_for component_specification binding_indication_semicolon_opt @@ -573,6 +578,12 @@ concurrent_signal_assignment_statement $$ = 0; yyerrok; } + | error LEQ waveform ';' + { errormsg(@1, "Syntax error in l-value of signal assignment.\n"); + yyerrok; + delete $3; + $$ = 0; + } ; concurrent_statement @@ -669,6 +680,15 @@ design_units /* Indicate the direction as a flag, with "downto" being TRUE. */ direction : K_to { $$ = false; } | K_downto { $$ = true; } ; +element_association + : choices ARROW expression + ; + +element_association_list + : element_association_list ',' element_association + | element_association + ; + /* As an entity is declared, add it to the map of design entities. */ entity_aspect : K_entity name @@ -1104,8 +1124,24 @@ name 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 + name. If none of the above, treat it as a array element select. */ | IDENTIFIER '(' expression ')' - { ExpName*tmp = new ExpName(lex_strings.make($1), $3); + { perm_string name = lex_strings.make($1); + delete[]$1; + if (const VType*type = active_scope->find_type(name)) { + ExpCast*tmp = new ExpCast(type, $3); + $$ = tmp; + } else { + ExpName*tmp = new ExpName(name, $3); + $$ = tmp; + } + FILE_NAME($$, @1); + } + | IDENTIFIER '(' range ')' + { ExpName*tmp = new ExpName(lex_strings.make($1), $3->msb(), $3->lsb()); FILE_NAME(tmp, @1); delete[]$1; $$ = tmp; @@ -1275,9 +1311,9 @@ primary } | STRING_LITERAL { ExpString*tmp = new ExpString($1); - FILE_NAME(tmp,@1); - delete[]$1; - $$ = tmp; + FILE_NAME(tmp,@1); + delete[]$1; + $$ = tmp; } | BITSTRING_LITERAL { ExpBitstring*tmp = new ExpBitstring($1); @@ -1285,8 +1321,22 @@ primary delete[]$1; $$ = tmp; } + + /* This catches function calls that use association lists for the + argument list. The position argument list is discovered elsewhere + and must be discovered by elaboration (thanks to the ambiguity of + VHDL syntax). */ + | IDENTIFIER '(' association_list ')' + { sorrymsg(@1, "Function calls not supported\n"); + $$ = 0; + } + | '(' expression ')' { $$ = $2; } + | '(' element_association_list ')' + { sorrymsg(@1, "Aggregate expressions not supported\n"); + $$ = 0; + } ; primary_unit @@ -1404,11 +1454,11 @@ process_sensitivity_list | name_list { $$ = $1; } ; + range : simple_expression direction simple_expression - { - range_t* tmp = new range_t($1, $3, $2); - $$ = tmp; + { range_t* tmp = new range_t($1, $3, $2); + $$ = tmp; } ; @@ -1683,6 +1733,18 @@ variable_assignment_statement FILE_NAME(tmp, @1); $$ = tmp; } + | name VASSIGN error ';' + { errormsg(@3, "Syntax error in r-value expression of assignment.\n"); + yyerrok; + delete $1; + $$ = 0; + } + | error VASSIGN expression ';' + { errormsg(@1, "Syntax error in l-value expression of assignment.\n"); + yyerrok; + delete $3; + $$ = 0; + } ; waveform diff --git a/vhdlpp/parse_types.h b/vhdlpp/parse_types.h index 2110c6ed5..7f08c9971 100644 --- a/vhdlpp/parse_types.h +++ b/vhdlpp/parse_types.h @@ -74,6 +74,9 @@ class range_t { ~range_t() { delete left_; delete right_; } void dump(ostream&out, int indent) const; + Expression*msb() { return direction_? left_ : right_; } + Expression*lsb() { return direction_? right_: left_; } + private: Expression *left_, *right_; bool direction_;