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:
parent
315ac4f179
commit
4748f0cb5e
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue