diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index d13acae1e..cf38d7531 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -219,13 +219,6 @@ 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_ << "'" @@ -268,6 +261,15 @@ void ExpEdge::dump(ostream&out, int indent) const dump_operand1(out, indent+3); } +void ExpFunc::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "function " << name_ + << " has " << argv_.size() << " arguments:" << endl; + for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { + argv_[idx]->dump(out, indent+2); + } +} + void ExpInteger::dump(ostream&out, int indent) const { out << setw(indent) << "" << "Integer " << value_ diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index c4567e106..de7435dcf 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -184,15 +184,6 @@ ExpBitstring::~ExpBitstring() { } -ExpCast::ExpCast(const VType*typ, Expression*arg) -: res_type_(typ), arg_(arg) -{ -} - -ExpCast::~ExpCast() -{ -} - ExpCharacter::ExpCharacter(char val) : value_(val) { @@ -233,6 +224,23 @@ ExpEdge::~ExpEdge() { } +ExpFunc::ExpFunc(perm_string nn) +: name_(nn), argv_(0) +{ +} + +ExpFunc::ExpFunc(perm_string nn, Expression*arg) +: name_(nn), argv_(1) +{ + argv_[0] = arg; +} + +ExpFunc::~ExpFunc() +{ + for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) + delete argv_[idx]; +} + ExpInteger::ExpInteger(int64_t val) : value_(val) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index a5385371e..f5cfb563b 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -209,23 +209,6 @@ 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 { @@ -292,6 +275,22 @@ class ExpEdge : public ExpUnary { private: fun_t fun_; }; +class ExpFunc : public Expression { + + public: + explicit ExpFunc(perm_string nn); + ExpFunc(perm_string nn, Expression*arg); + ~ExpFunc(); + + public: // Base methods + 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: + perm_string name_; + std::vector argv_; +}; class ExpInteger : public Expression { diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 30cd63f97..5ce4c4ddd 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -180,19 +180,6 @@ 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); @@ -233,6 +220,18 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty return errors; } +int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) +{ + int errors = 0; + + for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { + const VType*tmp = argv_[idx]->probe_type(ent, arc); + errors += argv_[idx]->elaborate_expr(ent, arc, tmp); + } + + return errors; +} + int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) { int errors = 0; diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index ffc6a4461..bdcd999f9 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -145,17 +145,6 @@ 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) { @@ -258,6 +247,34 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc) return errors; } +int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + + if (name_ == "unsigned" && argv_.size()==1) { + // Handle the special case that this is a cast to + // unsigned. This function is brought in as part of the + // std numeric library, but we interpret it as the same + // as the $unsigned function. + out << "$unsigned("; + errors += argv_[0]->emit(out, ent, arc); + out << ")"; + + } else if (name_ == "std_logic_vector" && argv_.size() == 1) { + // Special case: The std_logic_vector function casts its + // argument to std_logic_vector. Internally, we don't + // have to do anything for that to work. + out << "("; + errors += argv_[0]->emit(out, ent, arc); + out << ")"; + } else { + cerr << get_fileline() << ": sorry: Don't know how to emit function '" << name_ << "'" << endl; + errors += 1; + } + + return errors; +} + int ExpInteger::emit(ostream&out, Entity*, Architecture*) { out << value_; diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 826b952c0..9273dbce2 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1131,11 +1131,11 @@ name | IDENTIFIER '(' expression ')' { perm_string name = lex_strings.make($1); delete[]$1; - if (const VType*type = active_scope->find_type(name)) { - ExpCast*tmp = new ExpCast(type, $3); + if (active_scope->is_vector_name(name)) { + ExpName*tmp = new ExpName(name, $3); $$ = tmp; } else { - ExpName*tmp = new ExpName(name, $3); + ExpFunc*tmp = new ExpFunc(name, $3); $$ = tmp; } FILE_NAME($$, @1); diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index c7f09d054..d1e6a3112 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -104,6 +104,34 @@ bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression* } } +Signal* ScopeBase::find_signal(perm_string by_name) const +{ + map::const_iterator cur = new_signals_.find(by_name); + if (cur == new_signals_.end()) { + cur = old_signals_.find(by_name); + if (cur == old_signals_.end()) + return 0; + else + return cur->second; + } else { + return cur->second; + } +} + +Variable* ScopeBase::find_variable(perm_string by_name) const +{ + map::const_iterator cur = new_variables_.find(by_name); + if (cur == new_variables_.end()) { + cur = old_variables_.find(by_name); + if (cur == old_variables_.end()) + return 0; + else + return cur->second; + } else { + return cur->second; + } +} + void ScopeBase::do_use_from(const ScopeBase*that) { for (map::const_iterator cur = that->old_components_.begin() @@ -142,6 +170,16 @@ void ScopeBase::do_use_from(const ScopeBase*that) } } +bool ActiveScope::is_vector_name(perm_string name) const +{ + if (find_signal(name)) + return true; + if (find_variable(name)) + return true; + + return false; +} + Scope::Scope(const ScopeBase&ref) : ScopeBase(ref) { @@ -163,31 +201,3 @@ ComponentBase* Scope::find_component(perm_string by_name) } else return cur->second; } - -Signal* Scope::find_signal(perm_string by_name) -{ - map::const_iterator cur = new_signals_.find(by_name); - if (cur == new_signals_.end()) { - cur = old_signals_.find(by_name); - if (cur == old_signals_.end()) - return 0; - else - return cur->second; - } else { - return cur->second; - } -} - -Variable* Scope::find_variable(perm_string by_name) -{ - map::const_iterator cur = new_variables_.find(by_name); - if (cur == new_variables_.end()) { - cur = old_variables_.find(by_name); - if (cur == old_variables_.end()) - return 0; - else - return cur->second; - } else { - return cur->second; - } -} diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index a374e72c6..10a096186 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -50,6 +50,9 @@ class ScopeBase { const VType* find_type(perm_string by_name); bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp); + Signal* find_signal(perm_string by_name) const; + Variable* find_variable(perm_string by_name) const; + protected: void cleanup(); @@ -97,9 +100,6 @@ class Scope : public ScopeBase { ComponentBase* find_component(perm_string by_name); - Signal* find_signal(perm_string by_name); - Variable* find_variable(perm_string by_name); - public: void dump_scope(ostream&out) const; @@ -125,6 +125,10 @@ class ActiveScope : public ScopeBase { void use_from(const ScopeBase*that) { do_use_from(that); } + // This function returns true if the name is a vectorable + // name. The parser uses this to distinguish between function + // calls and array index operations. + bool is_vector_name(perm_string name) const; /* All bind_name function check if the given name was present * in previous scopes. If it is found, it is erased (but the pointer