From d9fea802da0a534b669f00cbbd5bf505a1ba431a Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 5 May 2013 19:05:46 -0700 Subject: [PATCH] Function declarations in packages This is still basic. Definitions are still not done. --- vhdlpp/debug.cc | 61 +++++++++++++++++++++++++++++++++++++++++--- vhdlpp/library.cc | 10 ++++++-- vhdlpp/package.cc | 9 +++++++ vhdlpp/parse.y | 23 ++++++++++++++--- vhdlpp/parse_wrap.h | 1 + vhdlpp/scope.cc | 21 ++++++++++++++- vhdlpp/scope.h | 18 ++++++++++--- vhdlpp/subprogram.cc | 54 +++++++++++++++++++++++++++++++++++++++ vhdlpp/subprogram.h | 51 ++++++++++++++++++++++++++++++++++++ vhdlpp/vtype.cc | 2 +- vhdlpp/vtype.h | 3 ++- 11 files changed, 237 insertions(+), 16 deletions(-) create mode 100644 vhdlpp/subprogram.cc create mode 100644 vhdlpp/subprogram.h diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 972150778..c85b868c3 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -22,6 +22,7 @@ # include "architec.h" # include "expression.h" # include "parse_types.h" +# include "sequential.h" # include "vsignal.h" # include "vtype.h" # include @@ -138,6 +139,19 @@ void Scope::dump_scope(ostream&out) const cur->second->dump(out, 3); else out << " signal " << cur->first.str() << ": ???" << endl; + } + // Dump subprograms + for (map::const_iterator cur = old_subprograms_.begin() + ; cur != old_subprograms_.end() ; ++cur) { + out << " subprogram " << cur->first << " is" << endl; + cur->second->dump(out); + out << " end subprogram " << cur->first << endl; + } + for (map::const_iterator cur = new_subprograms_.begin() + ; cur != new_subprograms_.end() ; ++cur) { + out << " subprogram " << cur->first << " is" << endl; + cur->second->dump(out); + out << " end subprogram " << cur->first << endl; } // Dump component declarations for (map::const_iterator cur = old_components_.begin() @@ -148,10 +162,11 @@ void Scope::dump_scope(ostream&out) const out << " end component " << cur->first << endl; } for (map::const_iterator cur = new_components_.begin() - ; cur != new_components_.end() ; ++cur) { - out << " component " << cur->first << " is" << endl; - cur->second->dump_ports(out); - out << " end component " << cur->first << endl; + ; cur != new_components_.end() ; ++cur) { + out << " component " << cur->first << " is" << endl; + cur->second->dump_generics(out); + cur->second->dump_ports(out); + out << " end component " << cur->first << endl; } } @@ -436,3 +451,41 @@ ostream& ExpInteger::dump_inline(ostream&out) const out << value_; return out; } + +void Subprogram::dump(ostream&fd) const +{ + fd << " " << name_; + + if (ports_->empty()) { + fd << "()"; + + } else { + fd << "("; + + list::const_iterator cur = ports_->begin(); + InterfacePort*curp = *cur; + fd << curp->name << ":"; + curp->type->show(fd); + + for (++ cur ; cur != ports_->end() ; ++ cur) { + curp = *cur; + fd << "; " << curp->name << ":"; + curp->type->show(fd); + } + fd << ")"; + } + + 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/library.cc b/vhdlpp/library.cc index 435778020..d009446bf 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -322,11 +322,13 @@ const VTypePrimitive* primitive_BOOLEAN = new VTypePrimitive(VTypePrimitive::BO const VTypePrimitive* primitive_BIT = new VTypePrimitive(VTypePrimitive::BIT); const VTypePrimitive* primitive_INTEGER = new VTypePrimitive(VTypePrimitive::INTEGER); const VTypePrimitive* primitive_STDLOGIC = new VTypePrimitive(VTypePrimitive::STDLOGIC); +const VTypePrimitive* primitive_CHARACTER= new VTypePrimitive(VTypePrimitive::CHARACTER); const VTypeRange* primitive_NATURAL = new VTypeRange(primitive_INTEGER, INT64_MAX, 0); -const VTypeArray* primitive_BIT_VECTOR = new VTypeArray(primitive_BIT, vector (1)); -const VTypeArray* primitive_BOOL_VECTOR = new VTypeArray(primitive_BOOLEAN, vector (1)); +static const VTypeArray* primitive_BIT_VECTOR = new VTypeArray(primitive_BIT, vector (1)); +static const VTypeArray* primitive_BOOL_VECTOR = new VTypeArray(primitive_BOOLEAN, vector (1)); +static const VTypeArray* primitive_STRING = new VTypeArray(primitive_CHARACTER, vector (1)); void generate_global_types(ActiveScope*res) { @@ -334,7 +336,9 @@ void generate_global_types(ActiveScope*res) res->bind_name(perm_string::literal("bit"), primitive_BIT); res->bind_name(perm_string::literal("integer"), primitive_INTEGER); res->bind_name(perm_string::literal("std_logic"), primitive_STDLOGIC); + res->bind_name(perm_string::literal("character"), primitive_CHARACTER); res->bind_name(perm_string::literal("bit_vector"),primitive_BOOL_VECTOR); + res->bind_name(perm_string::literal("string"), primitive_STRING); res->bind_name(perm_string::literal("natural"), primitive_NATURAL); } @@ -344,7 +348,9 @@ bool is_global_type(perm_string name) if (name == "bit") return true; if (name == "integer") return true; if (name == "std_logic") return true; + if (name == "character") return true; if (name == "bit_vector") return true; + if (name == "string") return true; if (name == "natural") return true; return false; } diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 338bbddae..2dd43ded3 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -104,6 +104,15 @@ void Package::write_to_stream(ostream&fd) const fd << ";" << endl; } + for (map::const_iterator cur = old_subprograms_.begin() + ; cur != old_subprograms_.end() ; ++cur) { + cur->second->write_to_stream(fd); + } + for (map::const_iterator cur = new_subprograms_.begin() + ; cur != new_subprograms_.end() ; ++cur) { + cur->second->write_to_stream(fd); + } + for (map::const_iterator cur = old_components_.begin() ; cur != old_components_.end() ; ++cur) { diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 3c4d0b174..e15c199ae 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -34,7 +34,8 @@ # include "architec.h" # include "expression.h" # include "sequential.h" -# include "package.h" +# include "subprogram.h" +# include "package.h" # include "vsignal.h" # include "vtype.h" # include @@ -234,6 +235,8 @@ static list* record_elements(list*names, Architecture::Statement* arch_statement; std::list* arch_statement_list; + + Subprogram*subprogram; }; /* The keywords are all tokens. */ @@ -341,6 +344,8 @@ static list* record_elements(list*names, %type else_when_waveform %type else_when_waveforms +%type function_specification subprogram_specification + %% /* The design_file is the root for the VHDL parse. This rule is also @@ -1143,6 +1148,15 @@ for_generate_statement function_specification /* IEEE 1076-2008 P4.2.1 */ : K_function IDENTIFIER '(' interface_list ')' K_return IDENTIFIER + { perm_string type_name = lex_strings.make($7); + perm_string name = lex_strings.make($2); + const VType*type_mark = active_scope->find_type(type_name); + Subprogram*tmp = new Subprogram(name, $4, type_mark); + FILE_NAME(tmp,@1); + delete[]$2; + delete[]$7; + $$ = tmp; + } ; generate_statement /* IEEE 1076-2008 P11.8 */ @@ -2057,6 +2071,7 @@ subprogram_body /* IEEE 1076-2008 P4.3 */ K_begin subprogram_statement_part K_end subprogram_kind_opt identifier_opt ';' { sorrymsg(@2, "Subprogram bodies not supported.\n"); + if ($1) delete $1; if ($8) delete[]$8; } @@ -2066,14 +2081,14 @@ subprogram_body /* IEEE 1076-2008 P4.3 */ subprogram_kind_opt identifier_opt ';' { errormsg(@2, "Syntax errors in subprogram body.\n"); yyerrok; + if ($1) delete $1; if ($8) delete[]$8; } ; subprogram_declaration : subprogram_specification ';' - { sorrymsg(@1, "Subprogram specifications not supported.\n"); - } + { if ($1) active_scope->bind_name($1->name(), $1); } ; subprogram_declarative_item /* IEEE 1079-2008 P4.3 */ @@ -2098,7 +2113,7 @@ subprogram_kind /* IEEE 1076-2008 P4.3 */ subprogram_kind_opt : subprogram_kind | ; subprogram_specification - : function_specification + : function_specification { $$ = $1; } ; /* This is an implementation of the rule: diff --git a/vhdlpp/parse_wrap.h b/vhdlpp/parse_wrap.h index d129fec43..ceca8439e 100644 --- a/vhdlpp/parse_wrap.h +++ b/vhdlpp/parse_wrap.h @@ -31,6 +31,7 @@ # include "architec.h" # include "expression.h" # include "sequential.h" +# include "subprogram.h" # include "parse_types.h" class VType; diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 0455f7a88..7d5ed1c8b 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -57,6 +57,11 @@ ScopeBase::ScopeBase(const ScopeBase&ref) insert_iterator >( old_types_, old_types_.end()) ); + merge(ref.old_subprograms_.begin(), ref.old_subprograms_.end(), + ref.new_subprograms_.begin(), ref.new_subprograms_.end(), + insert_iterator >( + old_subprograms_, old_subprograms_.end()) + ); } ScopeBase::~ScopeBase() @@ -76,6 +81,7 @@ void ScopeBase::cleanup() delete_all(new_components_); delete_all(new_types_); delete_all(new_constants_); + delete_all(new_subprograms_); } const VType*ScopeBase::find_type(perm_string by_name) @@ -146,13 +152,26 @@ void ScopeBase::do_use_from(const ScopeBase*that) continue; old_components_[cur->first] = cur->second; } - for (map::const_iterator cur = that->new_components_.begin() + for (map::const_iterator cur = that->new_components_.begin() ; cur != that->new_components_.end() ; ++ cur) { if (cur->second == 0) continue; old_components_[cur->first] = cur->second; } + for (map::const_iterator cur = that->old_subprograms_.begin() + ; cur != that->old_subprograms_.end() ; ++ cur) { + if (cur->second == 0) + continue; + old_subprograms_[cur->first] = cur->second; + } + for (map::const_iterator cur = that->new_subprograms_.begin() + ; cur != that->new_subprograms_.end() ; ++ cur) { + if (cur->second == 0) + continue; + old_subprograms_[cur->first] = cur->second; + } + for (map::const_iterator cur = that->old_types_.begin() ; cur != that->old_types_.end() ; ++ cur) { if (cur->second == 0) diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index e0fbfb0b3..e07e06ff6 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -23,12 +23,14 @@ # include # include # include "StringHeap.h" -# include "entity.h" -# include "expression.h" -# include "vsignal.h" +# include "entity.h" +# include "expression.h" +# include "subprogram.h" +# include "vsignal.h" class Architecture; class ComponentBase; +class Subprogram; class VType; template @@ -89,6 +91,9 @@ class ScopeBase { std::map old_constants_; //previous scopes std::map new_constants_; //current scope + std::map old_subprograms_; //previous scopes + std::map new_subprograms_; //current scope + void do_use_from(const ScopeBase*that); }; @@ -171,6 +176,13 @@ class ActiveScope : public ScopeBase { new_constants_[name] = new const_t(obj, val); } + void bind_name(perm_string name, Subprogram*obj) + { map::iterator it; + if((it = old_subprograms_.find(name)) != old_subprograms_.end() ) + old_subprograms_.erase(it); + new_subprograms_[name] = obj;; + } + void bind(Entity*ent) { context_entity_ = ent; } diff --git a/vhdlpp/subprogram.cc b/vhdlpp/subprogram.cc new file mode 100644 index 000000000..3aa1fb94b --- /dev/null +++ b/vhdlpp/subprogram.cc @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013 Stephen Williams (steve@icarus.com) + * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include "subprogram.h" +# include "entity.h" +# include "vtype.h" + +using namespace std; + +Subprogram::Subprogram(perm_string nam, list*ports, + const VType*return_type) +: name_(nam), ports_(ports), return_type_(return_type), statements_(0) +{ +} + +Subprogram::~Subprogram() +{ +} + +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; +} diff --git a/vhdlpp/subprogram.h b/vhdlpp/subprogram.h new file mode 100644 index 000000000..afd4764eb --- /dev/null +++ b/vhdlpp/subprogram.h @@ -0,0 +1,51 @@ +#ifndef __subprogram_H +#define __subprogram_H +/* + * Copyright (c) 2013 Stephen Williams (steve@icarus.com) + * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +# include "StringHeap.h" +# include "LineInfo.h" +# include +# include + +class InterfacePort; +class SequentialStmt; +class VType; + +class Subprogram : public LineInfo { + + public: + Subprogram(perm_string name, std::list*ports, + const VType*return_type); + ~Subprogram(); + + inline const perm_string&name() const { return name_; } + + void write_to_stream(std::ostream&fd) const; + void dump(std::ostream&fd) const; + + private: + perm_string name_; + std::list*ports_; + const VType*return_type_; + std::list*statements_; +}; + +#endif diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index b8e704d11..3c6d78241 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -32,7 +32,7 @@ VType::~VType() void VType::show(ostream&out) const { - out << typeid(*this).name(); + write_to_stream(out); } VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt) diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 4da22363d..3edbe44a2 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -112,7 +112,7 @@ class VTypeERROR : public VType { class VTypePrimitive : public VType { public: - enum type_t { BOOLEAN, BIT, INTEGER, STDLOGIC }; + enum type_t { BOOLEAN, BIT, INTEGER, STDLOGIC, CHARACTER }; public: VTypePrimitive(type_t); @@ -134,6 +134,7 @@ extern const VTypePrimitive* primitive_BOOLEAN; extern const VTypePrimitive* primitive_BIT; extern const VTypePrimitive* primitive_INTEGER; extern const VTypePrimitive* primitive_STDLOGIC; +extern const VTypePrimitive* primitive_CHARACTER; /* * An array is a compound N-dimensional array of element type. The