diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index d0d3fb1ff..7164f5fad 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -101,7 +101,7 @@ int Architecture::emit(ostream&out, Entity*entity) errors += emit_signals(out, entity, this); errors += emit_variables(out, entity, this); - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { // Do not emit unbounded functions, we will just need fixed instances later if(!cur->second->unbounded()) diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 890fe4f35..71ca0abd4 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -150,17 +150,21 @@ void Scope::dump_scope(ostream&out) const } // Dump subprograms out << " -- Imported Subprograms" << endl; - for (map::const_iterator cur = use_subprograms_.begin() + for (map::const_iterator cur = use_subprograms_.begin() ; cur != use_subprograms_.end() ; ++cur) { out << " subprogram " << cur->first << " is" << endl; cur->second->dump(out); + if(cur->second->body()) + cur->second->body()->dump(out); out << " end subprogram " << cur->first << endl; } out << " -- Subprograms from this scope" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { out << " subprogram " << cur->first << " is" << endl; cur->second->dump(out); + if(cur->second->body()) + cur->second->body()->dump(out); out << " end subprogram " << cur->first << endl; } // Dump component declarations @@ -467,7 +471,20 @@ ostream& ExpReal::dump_inline(ostream&out) const return out; } -void Subprogram::dump(ostream&fd) const +void SubprogramBody::dump(ostream&fd) const +{ + if (statements_== 0 || statements_->empty()) { + fd << " " << endl; + } else { + for (list::const_iterator cur = statements_->begin() + ; cur != statements_->end() ; ++cur) { + SequentialStmt*curp = *cur; + curp->dump(fd, 8); + } + } +} + +void SubprogramHeader::dump(ostream&fd) const { fd << " " << name_; @@ -493,14 +510,4 @@ void Subprogram::dump(ostream&fd) const fd << " return "; return_type_->show(fd); fd << endl; - - if (statements_== 0 || statements_->empty()) { - fd << " " << endl; - } else { - for (list::const_iterator cur = statements_->begin() - ; cur != statements_->end() ; ++cur) { - SequentialStmt*curp = *cur; - curp->dump(fd, 8); - } - } } diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 0847244b5..3049c45e7 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -32,7 +32,7 @@ class prange_t; class Entity; class ScopeBase; -class Subprogram; +class SubprogramHeader; class VType; class VTypeArray; class VTypePrimitive; @@ -564,7 +564,7 @@ class ExpFunc : public Expression { private: perm_string name_; std::vector argv_; - Subprogram*def_; + SubprogramHeader*def_; }; class ExpInteger : public Expression { diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 3da6b94a5..c8f014f05 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -777,7 +777,7 @@ const VType*ExpFunc::probe_type(Entity*ent, ScopeBase*scope) const return new VTypeArray(&primitive_STDLOGIC, msb, 0); } - Subprogram*prog = scope->find_subprogram(name_); + SubprogramHeader*prog = scope->find_subprogram(name_); if(!prog) prog = library_find_subprogram(name_); @@ -793,7 +793,7 @@ int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) int errors = 0; ivl_assert(*this, scope); - Subprogram*prog = scope->find_subprogram(name_); + SubprogramHeader*prog = scope->find_subprogram(name_); if(!prog) prog = library_find_subprogram(name_); @@ -878,7 +878,7 @@ const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) c } // Other cases - Subprogram*prog = def_; + SubprogramHeader*prog = def_; if(!prog) { ivl_assert(*this, scope); diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index b0594c38d..e6fee4d82 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -72,9 +72,9 @@ void library_add_directory(const char*directory) library_search_path.push_front(directory); } -Subprogram*library_find_subprogram(perm_string name) +SubprogramHeader*library_find_subprogram(perm_string name) { - Subprogram*subp = NULL; + SubprogramHeader*subp = NULL; map::const_iterator lib_it; for(lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) { diff --git a/vhdlpp/library.h b/vhdlpp/library.h index fe04aad23..a161f1cd0 100644 --- a/vhdlpp/library.h +++ b/vhdlpp/library.h @@ -19,12 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -class Subprogram; +class SubprogramHeader; extern void library_set_work_path(const char*work_path); extern void library_add_directory(const char*directory); -extern Subprogram*library_find_subprogram(perm_string name); +extern SubprogramHeader*library_find_subprogram(perm_string name); extern void emit_std_types(ostream&out); extern int emit_packages(void); diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 167c8a279..cf6e74652 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -111,9 +111,10 @@ void Package::write_to_stream(ostream&fd) const fd << ";" << endl; } - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { cur->second->write_to_stream(fd); + fd << ";" << endl; } for (map::const_iterator cur = old_components_.begin() @@ -130,9 +131,14 @@ void Package::write_to_stream(ostream&fd) const fd << "end package " << name_ << ";" << endl; fd << "package body " << name_ << " is" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { - cur->second->write_to_stream_body(fd); + SubprogramHeader*subp = cur->second; + if(subp->body()) { + subp->write_to_stream(fd); + fd << " is" << endl; + subp->body()->write_to_stream(fd); + } } fd << "end " << name_ << ";" << endl; } diff --git a/vhdlpp/package.h b/vhdlpp/package.h index a8e303cd5..fb6bfb8ac 100644 --- a/vhdlpp/package.h +++ b/vhdlpp/package.h @@ -36,7 +36,7 @@ class Package : public Scope, public LineInfo { perm_string name() const { return name_; } - Subprogram* recall_subprogram(perm_string name) const; + SubprogramHeader* recall_subprogram(perm_string name) const; // This method writes a package header to a library file. void write_to_stream(std::ostream&fd) const; diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc index d8db4494d..77d314231 100644 --- a/vhdlpp/package_emit.cc +++ b/vhdlpp/package_emit.cc @@ -64,7 +64,7 @@ int Package::emit_package(ostream&fd) const //} fd << "package \\" << name() << " ;" << endl; - for (map::const_iterator cur = cur_subprograms_.begin() + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { // Do not emit unbounded functions, we will just need fixed instances later if(!cur->second->unbounded()) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 29512b178..3536a6660 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -83,7 +83,7 @@ extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner); */ static ActiveScope*active_scope = new ActiveScope; static stack scope_stack; -static Subprogram*active_sub = NULL; +static SubprogramHeader*active_sub = NULL; // perm_strings for attributes const static perm_string left_attr = perm_string::literal("left"); @@ -262,7 +262,7 @@ static void touchup_interface_for_functions(std::list*ports) ReportStmt::severity_t severity; - Subprogram*subprogram; + SubprogramHeader*subprogram; }; /* The keywords are all tokens. */ @@ -374,6 +374,7 @@ static void touchup_interface_for_functions(std::list*ports) %type else_when_waveforms selected_waveform_list %type function_specification subprogram_specification subprogram_body_start + %type severity severity_opt %% @@ -1246,8 +1247,8 @@ function_specification /* IEEE 1076-2008 P4.2.1 */ perm_string name = lex_strings.make($2); const VType*type_mark = active_scope->find_type(type_name); touchup_interface_for_functions($4); - Subprogram*tmp = new Subprogram(name, $4, type_mark); - FILE_NAME(tmp,@1); + SubprogramHeader*tmp = new SubprogramHeader(name, $4, type_mark); + FILE_NAME(tmp, @1); delete[]$2; delete[]$7; $$ = tmp; @@ -2420,16 +2421,20 @@ subprogram_body /* IEEE 1076-2008 P4.3 */ : subprogram_body_start subprogram_declarative_part K_begin subprogram_statement_part K_end subprogram_kind_opt identifier_opt ';' - { Subprogram*prog = $1; - Subprogram*tmp = active_scope->recall_subprogram(prog->name()); + { SubprogramHeader*prog = $1; + SubprogramHeader*tmp = active_scope->recall_subprogram(prog->name()); if (tmp && prog->compare_specification(tmp)) { delete prog; prog = tmp; } else if (tmp) { errormsg(@1, "Subprogram specification for %s doesn't match specification in package header.\n", prog->name().str()); } - prog->transfer_from(*active_scope, ScopeBase::VARIABLES); - prog->set_program_body($4); + + SubprogramBody*body = new SubprogramBody(); + body->transfer_from(*active_scope, ScopeBase::VARIABLES); + body->set_statements($4); + + prog->set_body(body); active_scope->bind_name(prog->name(), prog); active_sub = NULL; } diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 49b422e89..c6f96a245 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -65,9 +65,9 @@ ScopeBase::ScopeBase(const ActiveScope&ref) // an active scope and is making the actual scope. At this point // we know that "this" is the parent scope for the subprograms, // so set it now. - for (map::iterator cur = cur_subprograms_.begin() - ; cur != cur_subprograms_.end() ; ++ cur) { - cur->second->set_parent(this); + for (map::iterator cur = cur_subprograms_.begin() + ; cur != cur_subprograms_.end(); ++cur) { + cur->second->set_parent(this); } } @@ -158,13 +158,13 @@ Variable* ScopeBase::find_variable(perm_string by_name) const const InterfacePort* ScopeBase::find_param(perm_string by_name) const { - for(map::const_iterator it = use_subprograms_.begin(); + for(map::const_iterator it = use_subprograms_.begin(); it != use_subprograms_.end(); ++it) { if(const InterfacePort*port = it->second->find_param(by_name)) return port; } - for(map::const_iterator it = cur_subprograms_.begin(); + for(map::const_iterator it = cur_subprograms_.begin(); it != cur_subprograms_.end(); ++it) { if(const InterfacePort*port = it->second->find_param(by_name)) return port; @@ -173,9 +173,9 @@ const InterfacePort* ScopeBase::find_param(perm_string by_name) const return NULL; } -Subprogram* ScopeBase::find_subprogram(perm_string name) const +SubprogramHeader* ScopeBase::find_subprogram(perm_string name) const { - map::const_iterator cur; + map::const_iterator cur; cur = cur_subprograms_.find(name); if (cur != cur_subprograms_.end()) @@ -218,7 +218,7 @@ void ScopeBase::do_use_from(const ScopeBase*that) old_components_[cur->first] = cur->second; } - for (map::const_iterator cur = that->cur_subprograms_.begin() + for (map::const_iterator cur = that->cur_subprograms_.begin() ; cur != that->cur_subprograms_.end() ; ++ cur) { if (cur->second == 0) continue; @@ -274,9 +274,9 @@ void ActiveScope::set_package_header(Package*pkg) package_header_ = pkg; } -Subprogram* ActiveScope::recall_subprogram(perm_string name) const +SubprogramHeader* ActiveScope::recall_subprogram(perm_string name) const { - if (Subprogram*tmp = find_subprogram(name)) + if (SubprogramHeader*tmp = find_subprogram(name)) return tmp; if (package_header_) diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 709e552ec..86990dc87 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -32,7 +32,7 @@ class ActiveScope; class Architecture; class ComponentBase; class Package; -class Subprogram; +class SubprogramHeader; class VType; template @@ -57,7 +57,7 @@ class ScopeBase { Signal* find_signal(perm_string by_name) const; Variable* find_variable(perm_string by_name) const; virtual const InterfacePort* find_param(perm_string by_name) const; - Subprogram* find_subprogram(perm_string by_name) const; + SubprogramHeader* find_subprogram(perm_string by_name) const; // Checks if a string is one of possible enum values. If so, the enum // type is returned, otherwise NULL. const VTypeEnum* is_enum_name(perm_string name) const; @@ -67,8 +67,8 @@ class ScopeBase { enum transfer_type_t { SIGNALS = 1, VARIABLES = 2, COMPONENTS = 4, ALL = 0xffff }; void transfer_from(ScopeBase&ref, transfer_type_t what = ALL); - inline void bind_subprogram(perm_string name, Subprogram*obj) - { map::iterator it; + inline void bind_subprogram(perm_string name, SubprogramHeader*obj) + { map::iterator it; if((it = use_subprograms_.find(name)) != use_subprograms_.end() ) use_subprograms_.erase(it); cur_subprograms_[name] = obj; @@ -116,8 +116,8 @@ class ScopeBase { std::map use_constants_; //imported constants std::map cur_constants_; //current constants - std::map use_subprograms_; //imported - std::map cur_subprograms_; //current + std::map use_subprograms_; //imported + std::map cur_subprograms_; //current std::list use_enums_; @@ -170,7 +170,7 @@ class ActiveScope : public ScopeBase { // Locate the subprogram by name. The subprogram body uses // this to locate the sobprogram declaration. Note that the // subprogram may be in a package header. - Subprogram* recall_subprogram(perm_string name) const; + SubprogramHeader* recall_subprogram(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 @@ -219,8 +219,8 @@ class ActiveScope : public ScopeBase { cur_constants_[name] = new const_t(obj, val); } - inline void bind_name(perm_string name, Subprogram*obj) - { map::iterator it; + inline void bind_name(perm_string name, SubprogramHeader*obj) + { map::iterator it; if((it = use_subprograms_.find(name)) != use_subprograms_.end() ) use_subprograms_.erase(it); cur_subprograms_[name] = obj; diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc index 8d2f4f814..aa62eee01 100644 --- a/vhdlpp/subprogram.cc +++ b/vhdlpp/subprogram.cc @@ -30,44 +30,61 @@ using namespace std; -Subprogram::Subprogram(perm_string nam, list*ports, - const VType*return_type) -: name_(nam), parent_(0), ports_(ports), return_type_(return_type), statements_(0) +SubprogramBody::SubprogramBody() + : statements_(NULL), header_(NULL) { } -Subprogram::~Subprogram() +SubprogramBody::~SubprogramBody() { } -void Subprogram::set_parent(const ScopeBase*par) +const InterfacePort*SubprogramBody::find_param(perm_string nam) const { - ivl_assert(*this, parent_ == 0); - parent_ = par; + if(!header_) + return NULL; + + return header_->find_param(nam); } -void Subprogram::set_program_body(list*stmt) +void SubprogramBody::set_statements(list*stmt) { ivl_assert(*this, statements_==0); statements_ = stmt; } -bool Subprogram::unbounded() const { - if(return_type_->is_unbounded()) - return true; +void SubprogramBody::write_to_stream(ostream&fd) const +{ + for (map::const_iterator cur = new_variables_.begin() + ; cur != new_variables_.end() ; ++cur) { + cur->second->write_to_stream(fd); + } - if(ports_) { - for(std::list::const_iterator it = ports_->begin(); - it != ports_->end(); ++it) { - if((*it)->type->is_unbounded()) - return true; - } - } + fd << "begin" << endl; - return false; + if (statements_) { + for (list::const_iterator cur = statements_->begin() + ; cur != statements_->end() ; ++cur) { + (*cur)->write_to_stream(fd); + } + } else { + fd << "--empty body" << endl; + } + fd << "end function;" << endl; } -bool Subprogram::compare_specification(Subprogram*that) const +SubprogramHeader::SubprogramHeader(perm_string nam, list*ports, + const VType*return_type) +: name_(nam), ports_(ports), return_type_(return_type), body_(NULL), parent_(NULL) +{ +} + +SubprogramHeader::~SubprogramHeader() +{ + delete body_; +} + +bool SubprogramHeader::compare_specification(SubprogramHeader*that) const { if (name_ != that->name_) return false; @@ -98,7 +115,7 @@ bool Subprogram::compare_specification(Subprogram*that) const return true; } -const InterfacePort*Subprogram::find_param(perm_string nam) const +const InterfacePort*SubprogramHeader::find_param(perm_string nam) const { if(!ports_) return NULL; @@ -112,7 +129,7 @@ const InterfacePort*Subprogram::find_param(perm_string nam) const return NULL; } -const VType*Subprogram::peek_param_type(int idx) const +const VType*SubprogramHeader::peek_param_type(int idx) const { if(!ports_ || idx < 0 || (size_t)idx >= ports_->size()) return NULL; @@ -123,7 +140,37 @@ const VType*Subprogram::peek_param_type(int idx) const return (*p)->type; } -Subprogram*Subprogram::make_instance(std::vector arguments, ScopeBase*scope) { +void SubprogramHeader::set_parent(const ScopeBase*par) +{ + ivl_assert(*this, !parent_); + parent_ = par; +} + +bool SubprogramHeader::unbounded() const { + if(return_type_->is_unbounded()) + return true; + + if(ports_) { + for(std::list::const_iterator it = ports_->begin(); + it != ports_->end(); ++it) { + if((*it)->type->is_unbounded()) + return true; + } + } + + return false; +} + +void SubprogramHeader::set_body(SubprogramBody*bdy) +{ + ivl_assert(*this, !body_); + body_ = bdy; + ivl_assert(*this, !bdy->header_); + bdy->header_ = this; +} + +SubprogramHeader*SubprogramHeader::make_instance(std::vector arguments, + ScopeBase*scope) { assert(arguments.size() == ports_->size()); std::list*ports = new std::list; @@ -142,25 +189,31 @@ Subprogram*Subprogram::make_instance(std::vector arguments, ScopeBa char buf[80]; snprintf(buf, sizeof(buf), "__%s_%p", name_.str(), ports); perm_string new_name = lex_strings.make(buf); - Subprogram*instance = new Subprogram(new_name, ports, return_type_); + SubprogramHeader*instance = new SubprogramHeader(new_name, ports, return_type_); - // Copy variables - for(std::map::iterator it = new_variables_.begin(); - it != new_variables_.end(); ++it) { - Variable*v = new Variable(it->first, it->second->peek_type()->clone()); - instance->new_variables_[it->first] = v; + if(body_) { + SubprogramBody*body_inst = new SubprogramBody(); + + // Copy variables + for(std::map::iterator it = body_->new_variables_.begin(); + it != body_->new_variables_.end(); ++it) { + Variable*v = new Variable(it->first, it->second->peek_type()->clone()); + body_inst->new_variables_[it->first] = v; + } + + body_inst->set_statements(body_->statements_); + instance->set_parent(scope); + instance->set_body(body_inst); + instance->fix_return_type(); } - instance->set_parent(scope); - instance->set_program_body(statements_); - instance->fix_return_type(); scope->bind_subprogram(new_name, instance); return instance; } struct check_return_type : public SeqStmtVisitor { - check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {} + check_return_type(const SubprogramBody*subp) : subp_(subp), ret_type_(NULL) {} void operator() (SequentialStmt*s) { @@ -195,54 +248,35 @@ struct check_return_type : public SeqStmtVisitor { const VType*get_type() const { return ret_type_; } private: - const Subprogram*subp_; + const SubprogramBody*subp_; const VType*ret_type_; }; -void Subprogram::fix_return_type() +void SubprogramHeader::fix_return_type() { - if(!statements_) + if(!body_ || !body_->statements_) return; - check_return_type r(this); + check_return_type r(body_); - for (std::list::iterator s = statements_->begin() - ; s != statements_->end(); ++s) { + for (std::list::iterator s = body_->statements_->begin() + ; s != body_->statements_->end(); ++s) { (*s)->visit(r); } VType*return_type = const_cast(r.get_type()); if(return_type && !return_type->is_unbounded()) { // Let's check if the variable length can be evaluated without any scope. - // If not, then it is depends on information about e.g. function params + // If not, then it depends on information about e.g. function params if(return_type->is_variable_length(NULL)) { if(VTypeArray*arr = dynamic_cast(return_type)) - arr->evaluate_ranges(this); + arr->evaluate_ranges(body_); } return_type_ = return_type; } } -void Subprogram::write_to_stream(ostream&fd) const -{ - fd << " function " << name_ << "("; - if (ports_ && ! ports_->empty()) { - list::const_iterator cur = ports_->begin(); - InterfacePort*curp = *cur; - fd << curp->name << " : "; - curp->type->write_to_stream(fd); - for (++cur ; cur != ports_->end() ; ++cur) { - curp = *cur; - fd << "; " << curp->name << " : "; - curp->type->write_to_stream(fd); - } - } - fd << ") return "; - return_type_->write_to_stream(fd); - fd << ";" << endl; -} - -void Subprogram::write_to_stream_body(ostream&fd) const +void SubprogramHeader::write_to_stream(ostream&fd) const { fd << "function " << name_ << "("; if (ports_ && ! ports_->empty()) { @@ -258,22 +292,4 @@ void Subprogram::write_to_stream_body(ostream&fd) const } fd << ") return "; return_type_->write_to_stream(fd); - fd << " is" << endl; - - for (map::const_iterator cur = new_variables_.begin() - ; cur != new_variables_.end() ; ++cur) { - cur->second->write_to_stream(fd); - } - - fd << "begin" << endl; - - if (statements_) { - for (list::const_iterator cur = statements_->begin() - ; cur != statements_->end() ; ++cur) { - (*cur)->write_to_stream(fd); - } - } else { - fd << "--empty body" << endl; - } - fd << "end function;" << endl; } diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h index 22c49879e..d0b05991d 100644 --- a/vhdlpp/subprogram.h +++ b/vhdlpp/subprogram.h @@ -27,51 +27,75 @@ # include "scope.h" # include # include +# include class InterfacePort; class SequentialStmt; class VType; +class SubprogramHeader; -class Subprogram : public LineInfo, public ScopeBase { +class SubprogramBody : public LineInfo, public ScopeBase { public: - Subprogram(perm_string name, std::list*ports, + SubprogramBody(); + ~SubprogramBody(); + + const InterfacePort*find_param(perm_string nam) const; + + void set_statements(std::list*statements); + inline bool empty_statements() const { return !statements_ || statements_->empty(); } + + int emit(ostream&out, Entity*ent, ScopeBase*scope); + + // Emit body as it would show up in a package. + int emit_package(std::ostream&fd) const; + + void write_to_stream(std::ostream&fd) const; + void dump(std::ostream&fd) const; + + private: + std::list*statements_; + SubprogramHeader*header_; + + friend class SubprogramHeader; +}; + +class SubprogramHeader : public LineInfo { + public: + SubprogramHeader(perm_string name, std::list*ports, const VType*return_type); - ~Subprogram(); - - void set_parent(const ScopeBase*par); - inline const ScopeBase*get_parent() const { return parent_; } - - inline const perm_string&name() const { return name_; } - - void set_program_body(std::list*statements); - inline bool empty_program_body() const { return !statements_ || statements_->empty(); } + ~SubprogramHeader(); // Return true if the specification (name, types, ports) // matches this subprogram and that subprogram. - bool compare_specification(Subprogram*that) const; + bool compare_specification(SubprogramHeader*that) const; const InterfacePort*find_param(perm_string nam) const; const VType*peek_param_type(int idx) const; const VType*peek_return_type() const { return return_type_; } - int emit(ostream&out, Entity*ent, ScopeBase*scope); + void set_parent(const ScopeBase*par); + inline const ScopeBase*get_parent() const { return parent_; } - // Emit a definition as it would show up in a package. - int emit_package(std::ostream&fd) const; + // Checks if either return type or parameters are unbounded vectors. + bool unbounded() const; - void write_to_stream(std::ostream&fd) const; - void write_to_stream_body(std::ostream&fd) const; - void dump(std::ostream&fd) const; + inline SubprogramBody*body() { return body_; } + void set_body(SubprogramBody*bdy); + + inline perm_string name() { return name_; } // Creates a new instance of the function that takes arguments of // a different type. It is used to allow VHDL functions that work with // unbounded std_logic_vectors, so there can be a separate instance // for limited length logic vector. - Subprogram*make_instance(std::vector arguments, ScopeBase*scope); + SubprogramHeader*make_instance(std::vector arguments, ScopeBase*scope); - // Checks if either return type or parameters are unbounded vectors. - bool unbounded() const; + // Emit header as it would show up in a package. + int emit_package(std::ostream&fd) const; + + void write_to_stream(std::ostream&fd) const; + void dump(std::ostream&fd) const; private: // Tries to set the return type to a fixed type. VHDL functions that @@ -79,11 +103,13 @@ class Subprogram : public LineInfo, public ScopeBase { // demands. void fix_return_type(); + // Procedure/function name perm_string name_; - const ScopeBase*parent_; + std::list*ports_; const VType*return_type_; - std::list*statements_; + SubprogramBody*body_; + const ScopeBase*parent_; }; #endif /* IVL_subprogram_H */ diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc index c2ae47cd8..fde37a178 100644 --- a/vhdlpp/subprogram_emit.cc +++ b/vhdlpp/subprogram_emit.cc @@ -25,7 +25,30 @@ using namespace std; -int Subprogram::emit_package(ostream&fd) const +int SubprogramBody::emit_package(ostream&fd) const +{ + int errors = 0; + + for (map::const_iterator cur = new_variables_.begin() + ; cur != new_variables_.end() ; ++cur) { + // Workaround to enable reg_flag for variables + cur->second->count_ref_sequ(); + errors += cur->second->emit(fd, NULL, NULL); + } + + if (statements_) { + for (list::const_iterator cur = statements_->begin() + ; cur != statements_->end() ; ++cur) { + errors += (*cur)->emit(fd, NULL, const_cast(this)); + } + } else { + fd << " begin /* empty body */ end" << endl; + } + + return errors; +} + +int SubprogramHeader::emit_package(ostream&fd) const { int errors = 0; @@ -63,21 +86,8 @@ int Subprogram::emit_package(ostream&fd) const fd << ");" << endl; - for (map::const_iterator cur = new_variables_.begin() - ; cur != new_variables_.end() ; ++cur) { - // Workaround to enable reg_flag for variables - cur->second->count_ref_sequ(); - errors += cur->second->emit(fd, NULL, NULL); - } - - if (statements_) { - for (list::const_iterator cur = statements_->begin() - ; cur != statements_->end() ; ++cur) { - errors += (*cur)->emit(fd, NULL, const_cast(this)); - } - } else { - fd << " begin /* empty body */ end" << endl; - } + if (body_) + body_->emit_package(fd); if (return_type_) fd << "endfunction" << endl; @@ -86,3 +96,23 @@ int Subprogram::emit_package(ostream&fd) const return errors; } + +int SubprogramHeader::emit_name(const std::vector&, + std::ostream&out, Entity*, ScopeBase*) const +{ + out << "\\" << name_; + return 0; +} + +int SubprogramHeader::emit_args(const std::vector&argv, + std::ostream&out, Entity*ent, ScopeBase*scope) const +{ + int errors = 0; + + for (size_t idx = 0; idx < argv.size() ; idx += 1) { + if (idx > 0) out << ", "; + errors += argv[idx]->emit(out, ent, scope); + } + + return errors; +}