Handle incomplete type declarations

Use these in the package library to allow for arbitrary mixing
of type declaration and use. This makes writing libraries much
easier.
This commit is contained in:
Stephen Williams 2012-05-05 15:15:45 -07:00
parent 315ac4f179
commit 4748f0cb5e
6 changed files with 105 additions and 12 deletions

View File

@ -40,6 +40,43 @@ void Package::write_to_stream(ostream&fd) const
{
fd << "package " << name_ << " is" << endl;
// Start out pre-declaring all the type definitions so that
// there is no confusion later in the package between types
// and identifiers.
for (map<perm_string,const VType*>::const_iterator cur = old_types_.begin()
; cur != old_types_.end() ; ++cur) {
const VTypeDef*def = dynamic_cast<const VTypeDef*> (cur->second);
if (def == 0)
continue;
fd << "type " << cur->first << ";" << endl;
}
for (map<perm_string,const VType*>::const_iterator cur = new_types_.begin()
; cur != new_types_.end() ; ++cur) {
const VTypeDef*def = dynamic_cast<const VTypeDef*> (cur->second);
if (def == 0)
continue;
fd << "type " << cur->first << ";" << endl;
}
for (map<perm_string,struct const_t*>::const_iterator cur = old_constants_.begin()
; cur != old_constants_.end() ; ++ cur) {
fd << "constant " << cur->first << ": ";
cur->second->typ->write_to_stream(fd);
fd << " := ";
cur->second->val->write_to_stream(fd);
fd << ";" << endl;
}
for (map<perm_string,struct const_t*>::const_iterator cur = new_constants_.begin()
; cur != new_constants_.end() ; ++ cur) {
fd << "constant " << cur->first << ": ";
cur->second->typ->write_to_stream(fd);
fd << " := ";
cur->second->val->write_to_stream(fd);
fd << ";" << endl;
}
for (map<perm_string,const VType*>::const_iterator cur = old_types_.begin()
; cur != old_types_.end() ; ++cur) {
@ -49,8 +86,8 @@ void Package::write_to_stream(ostream&fd) const
if (cur->first == "std_logic_vector")
continue;
fd << cur->first << ": ";
cur->second->write_to_stream(fd);
fd << "type " << cur->first << " is ";
cur->second->write_type_to_stream(fd);
fd << ";" << endl;
}
for (map<perm_string,const VType*>::const_iterator cur = new_types_.begin()
@ -62,8 +99,8 @@ void Package::write_to_stream(ostream&fd) const
if (cur->first == "std_logic_vector")
continue;
fd << cur->first << ": ";
cur->second->write_to_stream(fd);
fd << "type " << cur->first << " is ";
cur->second->write_type_to_stream(fd);
fd << ";" << endl;
}

View File

@ -1605,7 +1605,6 @@ package_body_declarative_part_opt
package_declarative_item
: component_declaration
| constant_declaration
| type_declaration
| subtype_declaration
| type_declaration
| use_clause
@ -2148,12 +2147,26 @@ type_declaration
if ($4 == 0) {
errormsg(@1, "Failed to declare type name %s.\n", name.str());
} else {
//VTypeDef*tmp = new VTypeDef(name, $4);
//active_scope->bind_name(name, tmp);
active_scope->bind_name(name, $4);
VTypeDef*tmp;
map<perm_string,VTypeDef*>::iterator cur = active_scope->incomplete_types.find(name);
if (cur == active_scope->incomplete_types.end()) {
tmp = new VTypeDef(name, $4);
active_scope->bind_name(name, tmp);
} else {
tmp = cur->second;
tmp->set_definition($4);
active_scope->incomplete_types.erase(cur);
}
}
delete[]$2;
}
| K_type IDENTIFIER ';'
{ perm_string name = lex_strings.make($2);
VTypeDef*tmp = new VTypeDef(name);
active_scope->incomplete_types[name] = tmp;
active_scope->bind_name(name, tmp);
delete[]$2;
}
| K_type IDENTIFIER K_is error ';'
{ errormsg(@4, "Error in type definition for %s\n", $2);
yyerrok;

View File

@ -179,6 +179,10 @@ class ActiveScope : public ScopeBase {
cleanup();
}
// Keep track of incomplete types until their proper
// definition shows up.
std::map<perm_string,VTypeDef*> incomplete_types;
private:
Entity*context_entity_;
};

View File

@ -21,6 +21,7 @@
# include "parse_types.h"
# include <map>
# include <typeinfo>
# include <cassert>
using namespace std;
@ -200,6 +201,11 @@ VTypeRecord::element_t::element_t(perm_string name, const VType*typ)
{
}
VTypeDef::VTypeDef(perm_string nam)
: name_(nam), type_(0)
{
}
VTypeDef::VTypeDef(perm_string nam, const VType*typ)
: name_(nam), type_(typ)
{
@ -208,3 +214,9 @@ VTypeDef::VTypeDef(perm_string nam, const VType*typ)
VTypeDef::~VTypeDef()
{
}
void VTypeDef::set_definition(const VType*typ)
{
assert(type_ == 0);
type_ = typ;
}

View File

@ -44,6 +44,10 @@ class VType {
// of this type to the designated stream. This is used for
// writing parsed types to library files.
virtual void write_to_stream(std::ostream&fd) const;
// This is like the above, but is the root function called
// directly after the "type <name> is..." when writing type
// definitions. Most types accept the default definition of this.
virtual void write_type_to_stream(std::ostream&fd) const;
// This virtual method writes a human-readable version of the
// type to a given file for debug purposes. (Question: is this
@ -226,9 +230,16 @@ class VTypeRecord : public VType {
class VTypeDef : public VType {
public:
VTypeDef(perm_string name, const VType*is);
explicit VTypeDef(perm_string name);
explicit VTypeDef(perm_string name, const VType*is);
~VTypeDef();
// If the type is not given a definition in the constructor,
// then this must be used to set the definition later.
void set_definition(const VType*is);
void write_to_stream(std::ostream&fd) const;
void write_type_to_stream(ostream&fd) const;
int emit_typedef(std::ostream&out) const;
int emit_def(std::ostream&out) const;

View File

@ -29,6 +29,11 @@ void VType::write_to_stream(ostream&fd) const
fd << "/* UNKNOWN TYPE: " << typeid(*this).name() << " */";
}
void VType::write_type_to_stream(ostream&fd) const
{
write_to_stream(fd);
}
void VTypeArray::write_to_stream(ostream&fd) const
{
// Special case: std_logic_vector
@ -76,6 +81,16 @@ void VTypeArray::write_to_stream(ostream&fd) const
etype_->write_to_stream(fd);
}
void VTypeDef::write_type_to_stream(ostream&fd) const
{
type_->write_to_stream(fd);
}
void VTypeDef::write_to_stream(ostream&fd) const
{
fd << name_;
}
void VTypePrimitive::write_to_stream(ostream&fd) const
{
switch (type_) {
@ -100,7 +115,8 @@ void VTypePrimitive::write_to_stream(ostream&fd) const
void VTypeRange::write_to_stream(ostream&fd) const
{
fd << "range " << min_ << " to " << max_;
base_->write_to_stream(fd);
fd << " range " << min_ << " to " << max_;
}
void VTypeRecord::write_to_stream(ostream&fd) const
@ -110,11 +126,11 @@ void VTypeRecord::write_to_stream(ostream&fd) const
elements_[idx]->write_to_stream(fd);
fd << "; ";
}
fd << "endrecord";
fd << "end record";
}
void VTypeRecord::element_t::write_to_stream(ostream&fd) const
{
fd << name_ << ":";
fd << name_ << ": ";
type_->write_to_stream(fd);
}